home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1810 / 1810.xpi / chrome / showcase.jar / content / showcase.js < prev    next >
Text File  |  2010-01-17  |  251KB  |  7,050 lines

  1. // Constants
  2. const NUMBER_BORDER_COLORS = 12;
  3. const ANIMATION_INTERVAL = 40;
  4. const STATE_START = Components.interfaces.nsIWebProgressListener.STATE_START;
  5. const STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP;
  6. const STATE_REDIRECTING= Components.interfaces.nsIWebProgressListener.STATE_REDIRECTING;
  7. const STATE_TRANSFERRING = Components.interfaces.nsIWebProgressListener.STATE_TRANSFERRING;
  8. const STATE_IS_DOCUMENT = Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT;
  9. const STATE_IS_WINDOW = Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW;
  10. const STATE_IS_REQUEST = Components.interfaces.nsIWebProgressListener.STATE_IS_REQUEST;
  11. const RELOAD_FLAGS = Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE;
  12. const RELOAD_SKIP_CACHE_FLAGS = Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
  13. const VK_SPACE = 32;
  14. const VK_PRIOR = 33;
  15. const VK_NEXT = 34;
  16. const IETAB_URL = "chrome://ietab/content/reloaded.html?url=";
  17. const SHOWCASE_SIDEBAR = "viewShowcaseSidebar";
  18. const SHOWCASETHISWINDOW_SIDEBAR = "viewShowcaseThisWindowSidebar";
  19. const OPTIONS_URL = "chrome://showcase/content/settings/settings.xul";
  20. const FINDTYPE_TITLE = 0;
  21. const FINDTYPE_LOCATION = 1;
  22. const FINDTYPE_CONTENT = 2;
  23. const FINDTYPE_ANY = 3;
  24. const SCROLL_NONE = 0;
  25. const SCROLL_VERTICAL = 1;
  26. const SCROLL_HORIZONTAL = 2;
  27. const CONTENTTYPE_HTML = "text/html";
  28. const CONTENTTYPE_XHTML = "application/xhtml+xml";
  29. const CONTENTTYPE_XUL = "application/vnd.mozilla.xul+xml";
  30. const CACHEMODE_NOTHING = 0;
  31. const CACHEMODE_CLEAR = 1;
  32. const CACHEMODE_UPDATE = 2;
  33.  
  34. // Identification var
  35. var isShowcaseWindow = true;
  36.  
  37. // Global vars
  38. var showcaseBox;
  39. var showcaseContentVertical;
  40. var selectionBox;
  41. var dropBox;
  42. var selectionStartX;
  43. var selectionStartY;
  44. var selectionEndX;
  45. var selectionEndY;
  46. var originalSelection = new Array();
  47. var originalGlobalMode;
  48. var globalMode;
  49. var topWindow;
  50. var targetFocusWindow;
  51. var currentAnimations = new Array();
  52. var loadingTabTitle;
  53. var untitledTabTitle;
  54. var closeTabTitle;
  55. var showcasePopupTab;
  56. var pendingThumbnails = new Array();
  57. var windowCurrentColor = 1;
  58. var thumbWidth, thumbHeight;
  59. var closingShowcase = false;
  60. var processedWindows = new Array();
  61. var currentCursor = null;
  62. var showcaseOriginalTitle = null;
  63. var tabOldStyle;
  64. var showcaseOldBackgroundColor;
  65. var paintThumbnailsThread;
  66. var findPhraseNotFoundLabel;
  67. var showOnlyCurrent =false;
  68. var showOnlyCurrentLabel = null;
  69. var localTargetWindow = null;
  70. var scrollBoxObject = null;
  71. var scrollActivated = false;
  72. var isWaitingRefocus = false;
  73. var lastMouseDownTab = null;
  74. var selectTimer = null;
  75. var selectTimerTarget = null;
  76. var currentIconsThumbnail = null;
  77. var thumbnailBackButtonObject = null;
  78. var thumbnailForwardButtonObject = null;
  79. var thumbnailReloadButtonObject = null;
  80. var thumbnailStopButtonObject = null;
  81. var thumbnailHistoryButtonObject = null;
  82. var isFirefox35;
  83.  
  84. // Selection bars
  85. var selectedTabs = new Array();
  86. var lastFocusedTab = null;
  87. var focusToggleSelection = false;
  88. var focusSelectRange = false;
  89. var focusIgnoreSelection = false;
  90. var focusSelectIfUnselected = false;
  91.  
  92. // Search variables
  93. var gFinder = Components.classes["@mozilla.org/embedcomp/rangefind;1"].createInstance()
  94.                         .QueryInterface(Components.interfaces.nsIFind);
  95. var searchCaseSensitive = false;
  96. var searchActive = false;
  97. var searchFindType = FINDTYPE_ANY;
  98. var lastSearch = "";
  99. var lastSearchFindType = FINDTYPE_ANY;
  100. var lastSearchCaseSensitive = false;
  101.  
  102. // Configuration parameters
  103. var coloredThumbnailsForMultipleWindows;
  104. var paintThumbnailsAfterLoading;
  105. var paintSelectedTabsFirst;
  106. var thumbnailActiveAnimation;
  107. var animationFrames;
  108. var thumbnailIdleSizeFactor;
  109. var thumbnailActiveSizeFactor;
  110. var windowAttributeMaximized;
  111. var windowAttributeFullScreen;
  112. var windowAttributeTranslucent;
  113. var updateThumbnailWhenContentLoaded;
  114. var updateThumbnailWhenScroll;
  115. var updateThumbnailWhenContentChanges;
  116. var updateThumbnailWhenTitleChanges;
  117. var limitContentChangeUpdates;
  118. var limitContentChangeUpdatesTime;
  119. var thumbnailShowLabels;
  120. var thumbnailLabelStyle;
  121. var leftClickAction;
  122. var middleClickAction;
  123. var rightClickAction;
  124. var showcaseCustomColors = false;
  125. var showcaseCustomTitleColor;
  126. var showcaseCustomBackgroundColor;
  127. var showcaseCloseWhenBlur;
  128. var showcaseCloseWhenParentFocus;
  129. var showcaseCloseWhenSelect;
  130. var showcaseCloseWhenZeroThumbnails;
  131. var thumbnailTooltipTitle;
  132. var thumbnailTooltipURL;
  133. var browserChromeURL;
  134. var showTitleStats;
  135. var scrollType;
  136. var thumbnailPreferredMinimumSize = 250;
  137. var alwaysShowScrollbar;
  138. var verticalScrollbarWidth;
  139. var horizontalScrollbarHeight;
  140. var useWindowZOrder;
  141. var selectWhenMouseOver = false;
  142. var selectWhenMouseOverDelay = 300;
  143. var hideTabBar = false;
  144. var synchFindBar = false;
  145. var showOnlyCurrentByDefault = false;
  146. var doubleClickOpen = false;
  147. var detectBlank;
  148. var detectIETab;
  149. var detectPlugin;
  150. var detectImage;
  151. var renderingType;
  152. var tabColorizeLabel;
  153. var closeLastTabKeepOpen;
  154. var dragDropExclude;
  155. var zoomScrollIncrement;
  156. var tabFlipping;
  157. var findBarMode;
  158. var thumbnailBackButton;
  159. var thumbnailForwardButton;
  160. var thumbnailStopButton;
  161. var thumbnailReloadButton;
  162. var thumbnailHistoryButton;
  163. var imageThumbnailUpscale = false;
  164. var zoomFitsScreen;
  165. var selectWhenOpen;
  166. var doubleClickAction;
  167. var newThumbnailStyle;
  168. var focusShowcase;
  169.  
  170. // Contextual menu actions
  171. var loadedContextualSettings = false;
  172. var contextualActionOpen;
  173. var contextualActionShowcaseThis;
  174. var contextualActionBack;
  175. var contextualActionForward;
  176. var contextualActionReload;
  177. var contextualActionStop;
  178. var contextualActionDuplicateTab;
  179. var contextualActionDuplicateSelected;
  180. var contextualActionMoveTab;
  181. var contextualActionMergeSelected;
  182. var contextualActionBookmarkPage;
  183. var contextualActionBookmarkSelected;
  184. var contextualActionSavePage;
  185. var contextualActionSendPage;
  186. var contextualActionPrint;
  187. var contextualActionViewSource;
  188. var contextualActionPageInfo;
  189. var contextualActionCloseOther;
  190. var contextualActionClose;
  191. var contextualActionCloseTab;
  192. var contextualActionCloseWindow;
  193.  
  194.  
  195. var gPref = Components.classes["@mozilla.org/preferences-service;1"]
  196.                .getService(Components.interfaces.nsIPrefService)
  197.                .QueryInterface(Components.interfaces.nsIPrefBranch2);
  198.  
  199.  
  200. // Mosaic vars
  201. var mosaicRows;
  202. var mosaicColumns;
  203. var mosaicWidth;
  204. var mosaicHeight;
  205.  
  206. // Zoom vars
  207. var inZoomMode = false;
  208. var zoomTargetThumbnail = null;
  209. var zoomTargetPreviousCursorStyle = null;
  210. var previousZoomScrollX = null;
  211. var previousZoomScrollY = null;
  212. var zoomScrollingUp = false;
  213. var zoomScrollingDown = false;
  214. var zoomScrollingLeft = false;
  215. var zoomScrollingRight = false;
  216. var zoomOffsetX = 0;
  217. var zoomOffsetY = 0
  218. var zoomTotalWidth;
  219. var zoomTotalHeight;
  220. var zoomCurrentWidth;
  221. var zoomCurrentHeight;
  222. var zoomCursorLeft;
  223. var zoomCursorRight;
  224. var zoomCursorUp;
  225. var zoomCursorDown;
  226.  
  227. // Size checked
  228. var thumbnailBorderWidth = -1;
  229. var thumbnailBorderHeight = -1;
  230.  
  231. // Version detector
  232. var isNewLayout = false;
  233.  
  234. // Intermediate cache for high quality thumbnails
  235. var intermediateCache = null;
  236.  
  237. // Observers
  238. var windowObserver = {
  239.   observe: function(subject,topic,data){
  240.     switch(topic){
  241.       case 'domwindowopened':
  242.         subject.addEventListener("load", newWindowLoaded, false);
  243.         break;
  244.       case 'domwindowclosed':
  245.         var targetProcessedWindow = getProcessedWindowForWindow(subject);
  246.         if (targetProcessedWindow) {
  247.           unlinkProcessedWindow(targetProcessedWindow, CACHEMODE_NOTHING);
  248.           if ((processedWindows.length == 0) && showcaseCloseWhenZeroThumbnails) {
  249.             showcaseCloseWindow();
  250.           } else {
  251.             if (processedWindows.length < 1) {
  252.               document.getElementById("emptyMessage").setAttribute("hidden", false);
  253.             }
  254.  
  255.             if (processedWindows.length == 1) {
  256.               updateBorders(processedWindows[0]);
  257.             }
  258.             updateTitle();
  259.             refreshContent();
  260.           }
  261.         }
  262.         break;
  263.     }
  264.   }
  265. };
  266.  
  267. // Array helper functions
  268. function removeAllElements(targetArray) {
  269.   targetArray.length = 0;
  270. }
  271.  
  272. function removeElementAt(targetArray, index) {
  273.   targetArray.splice(index, 1);
  274. }
  275.  
  276. function insertElementAt(targetArray, element, index) {
  277.   targetArray.splice(index, 0, element);
  278. }
  279.  
  280. function startup() {
  281.   showcaseBox = document.getElementById("showcase-box");
  282.   showcaseContentVertical = document.getElementById("showcase-content-vertical");
  283.   selectionBox = document.getElementById("selection-box");
  284.   dropBox = document.getElementById("drop-box");
  285.   
  286.   // Detect version
  287.   var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
  288.                         .getService(Components.interfaces.nsIXULAppInfo)
  289.   var versionChecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
  290.                         .getService(Components.interfaces.nsIVersionComparator);
  291.   // if the engine version is 1.9, we're using the new layout engine
  292.   if (versionChecker.compare(appInfo.platformVersion, "1.9a1") >= 0) {
  293.     isNewLayout = true;
  294.   }
  295.   
  296.   if (versionChecker.compare(appInfo.platformVersion, "1.9.1a1") >= 0) {
  297.     isFirefox35 = true;
  298.   }
  299.  
  300.   // Guess if we want single window mode or multi window
  301.   if (window.location.search) {
  302.     var globalModeParameter = window.location.search.substr("?global=".length, window.location.search.length);
  303.     globalMode = ((globalModeParameter == "true") || (globalModeParameter == "yes"));
  304.   } else {
  305.     globalMode = false;
  306.   }
  307.  
  308.   originalGlobalMode = globalMode;
  309.  
  310.   // Set top window if needed
  311.   topWindow = QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebNavigation).QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow);
  312.  
  313.   /*
  314.   if (topWindow != window) {
  315.     // We're embedded (tab or sidebar)
  316.     if (window.top == topWindow) {
  317.       // Sidebar
  318.     }
  319.   }
  320.   */
  321.  
  322.   showcaseBox.setAttribute("focusable", "true");
  323.   
  324.   if (isFirefox35) {
  325.     showcaseBox.setAttribute("ondragover", "newDragDropHandler.onDragOver(event);");
  326.     showcaseBox.setAttribute("ondrop", "newDragDropHandler.onDrop(event);");
  327.   } else {
  328.     showcaseBox.setAttribute("ondragover", "nsDragAndDrop.dragOver(event,boardObserver)");
  329.     showcaseBox.setAttribute("ondragdrop", "nsDragAndDrop.drop(event,boardObserver)");
  330.   }
  331.   
  332.   loadSettings();
  333.  
  334.   if (focusShowcase) {
  335.     setTimeout(function (target) { target.focus(); }, 0, showcaseBox);
  336.   }
  337.  
  338.   // Default settings
  339.   showOnlyCurrent = showOnlyCurrentByDefault;
  340.  
  341.   initShowcase();
  342.  
  343.   if ((topWindow == window) && (windowAttributeFullScreen || windowAttributeMaximized)) {
  344.     // Invoke it "later", when window is created. If we don't do this, we won't overlap the taskbar in Windows
  345.     setTimeout(activateFullScreen, 0);
  346.   } else {
  347.     // Proceed
  348.     contentStartup(thumbnailActiveAnimation);
  349.     
  350.     // Check synch find bar in tab mode
  351.     if (synchFindBar && (topWindow != window.top)) {
  352.       checkSynchFindBar(topWindow, this);
  353.     }
  354.     
  355.   }
  356. }
  357.  
  358. function initShowcase() {
  359.   // set the correct scrolling
  360.   if (scrollType != SCROLL_NONE) {
  361.     scrollBoxObject = showcaseContentVertical.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
  362.   } else {
  363.     scrollBoxObject = null;
  364.   }
  365.  
  366.   if (showcaseCustomColors) {
  367.     if (isNewLayout) {
  368.       showcaseBox.style.setProperty('background-color', showcaseCustomBackgroundColor, '');
  369.     } else {
  370.       showcaseBox.style.backgroundColor = showcaseCustomBackgroundColor + " !important;";
  371.     }
  372.  
  373.     if ((window.top != topWindow) && (tabColorizeLabel)) {
  374.       // We're a tab, set the style...
  375.       var tabbrowser = topWindow.getBrowser();
  376.       var donePaint = false;
  377.       if (tabbrowser.mCurrentTab && (tabbrowser.mCurrentTab.linkedBrowser.contentWindow == window)) {
  378.         setTabColor(tabbrowser.mCurrentTab, topWindow.document);
  379.       } else {
  380.         for (var i = 0; (i < tabbrowser.mTabContainer.childNodes.length) && !donePaint; i++) {
  381.           var tab = tabbrowser.mTabContainer.childNodes[i];
  382.           if (tab.linkedBrowser.contentWindow == window) {
  383.             setTabColor(tab, topWindow.document);
  384.             donePaint = true;
  385.           }
  386.         }
  387.       }
  388.       window.focus();
  389.     }
  390.   }
  391.  
  392.   if (showcaseCloseWhenParentFocus) {
  393.     try {
  394.       window.opener.addEventListener("focus", showcaseParentGotFocus, true);
  395.     } catch (e) {}
  396.   }
  397.  
  398. //  window.addEventListener("focus", showcaseGainedFocus, false);
  399.   window.addEventListener("blur", showcaseLostFocus, false);
  400.  
  401.   if (windowAttributeTranslucent) {
  402.     try {
  403.       var translucentWindowCss = window.document.createProcessingInstruction("xml-stylesheet","type=\"text/css\" href=\"chrome://showcase/skin/translucentWindow.css\"");
  404.       window.hidden = true;
  405.       window.document.insertBefore(translucentWindowCss, window.document.documentElement);
  406.     } catch (e) { alert("startup - " + e); }
  407.   }
  408.  
  409.   if (window.sidebarFindBar) {
  410.     if (findBarMode == 0) {
  411.       searchActive = true;
  412.       document.getElementById("FindToolbar").hidden = false;
  413.       document.getElementById("find-closebutton").hidden = true;
  414.     } else if (findBarMode == 1) {
  415.       searchActive = false;
  416.       document.getElementById("FindToolbar").hidden = true;
  417.       document.getElementById("find-closebutton").hidden = true;
  418.     } else {
  419.       document.getElementById("FindToolbar").hidden = !searchActive;
  420.       document.getElementById("find-closebutton").hidden = false;
  421.     }
  422.   }
  423. }
  424.  
  425. function showcaseParentGotFocus() {
  426.   if (!isWaitingRefocus) {
  427.     showcaseCloseWindow();
  428.   }
  429. }
  430.  
  431. // To unlink a tab from the events structure
  432. function unlinkProcessedTab(processedTab, tabWindow) {
  433.   try {
  434.  
  435.   if (selectedTabs.indexOf(processedTab) > -1) {
  436.     removeElementAt(selectedTabs, selectedTabs.indexOf(processedTab));
  437.   }
  438.  
  439.   if (processedTab.showcaseCanvasBox) {
  440.     // Remove from current animations if it's there
  441.     if (thumbnailActiveAnimation) {
  442.       var animationPos = currentAnimations.indexOf(processedTab.showcaseCanvasBox);
  443.       if (animationPos > -1) {
  444.         removeElementAt(currentAnimations, animationPos);
  445.       }
  446.     }
  447.  
  448.     if (currentCursor == processedTab) {
  449.       // Select next
  450.       var targetRow = currentCursor.showcaseRow;
  451.       var targetColumn = currentCursor.showcaseColumn;
  452.  
  453.       if (targetColumn < mosaicColumns - 1) {
  454.         targetColumn++;
  455.       } else {
  456.         targetColumn = 0;
  457.         targetRow++;
  458.       }
  459.       var result = getTabAt(targetRow, targetColumn);
  460.  
  461.       if (result) {
  462.         if (currentCursor == result) {
  463.           // No change, go to previous
  464.           targetRow = currentCursor.showcaseRow;
  465.           targetColumn = currentCursor.showcaseColumn;
  466.  
  467.           if (targetColumn > 0) {
  468.             targetColumn--;
  469.           } else if (targetRow > 0) {
  470.             targetRow--;
  471.             targetColumn = mosaicColumns - 1;
  472.           } else {
  473.             currentCursor = null;
  474.             targetRow = -1;
  475.           }
  476.  
  477.           if (targetRow > -1) {
  478.             var result = getTabAt(targetRow, targetColumn);
  479.  
  480.             if (result) {
  481.               if (currentCursor == result) {
  482.                 currentCursor = null;
  483.               } else {
  484.                 focusIgnoreSelection = true;
  485.                 result.showcaseCanvasBox.focus();
  486.               }
  487.             }
  488.           }
  489.         } else {
  490.           focusIgnoreSelection = true;
  491.           result.showcaseCanvasBox.focus();
  492.         }
  493.       }
  494.     }
  495.  
  496.     // Check if it has the icons
  497.     if ((currentIconsThumbnail != null) && (currentIconsThumbnail.showcaseTab == processedTab)) {
  498.       hideThumbnailIcons();
  499.       currentIconsThumbnail = null;
  500.     }
  501.  
  502.     // Remove event listeners
  503.     processedTab.showcaseCanvasBox.removeEventListener("focus", thumbnailFocus, false);
  504.     processedTab.showcaseCanvasBox.removeEventListener("blur", thumbnailBlur, false);
  505.     if (thumbnailActiveAnimation || selectWhenMouseOver || thumbnailBackButton || thumbnailForwardButton || thumbnailStopButton || thumbnailReloadButton || thumbnailHistoryButton) {
  506.       processedTab.showcaseCanvasBox.removeEventListener("mouseover", mouseOverCanvas, false);
  507.       processedTab.showcaseCanvasBox.removeEventListener("mouseout", mouseOutCanvas, false);
  508.     }
  509.     processedTab.showcaseCanvasBox.removeEventListener("mousedown", mouseDownCanvas, (topWindow != window));
  510.     processedTab.showcaseCanvasBox.removeEventListener("mouseup", mouseUpCanvas, (topWindow != window));
  511.     if (doubleClickOpen) {
  512.       processedTab.showcaseCanvasBox.removeEventListener("dblclick", mouseDoubleClickCanvas, (topWindow != window));
  513.     }
  514.  
  515.     while (processedTab.showcaseCanvasBox.hasChildNodes()) {
  516.       processedTab.showcaseCanvasBox.removeChild(processedTab.showcaseCanvasBox.firstChild);
  517.     }
  518.     processedTab.showcaseCanvasBox.showcaseCanvas = undefined;
  519.     processedTab.showcaseCanvasBox.showcaseTab = undefined;
  520.     processedTab.showcaseCanvasBox.showcaseLabel = undefined;
  521.     processedTab.showcaseCanvasBox.showcaseImageLabel = undefined;
  522.     processedTab.showcaseCanvasBox.showcaseCloseButton = undefined;
  523.     processedTab.showcaseCanvasBox = undefined;
  524.  
  525.     if (processedTab.showcaseCanvasSubBox) {
  526.       while (processedTab.showcaseCanvasSubBox.hasChildNodes()) {
  527.         processedTab.showcaseCanvasSubBox.removeChild(processedTab.showcaseCanvasSubBox.firstChild);
  528.       }
  529.       processedTab.showcaseCanvasSubBox = undefined;
  530.     }
  531.   }
  532.   
  533.   if (processedTab._scrollTimer) {
  534.     processedTab._scrollTimer.cancel();
  535.     processedTab._scrollTimer = undefined;
  536.   }
  537.  
  538.   processedTab.showcaseIETab = undefined;
  539.   processedTab.showcaseBlank = undefined;
  540.   processedTab.showcaseEmbedded = undefined;
  541.  
  542.   if (processedTab.showcaseProgressListener) {
  543.     processedTab.showcaseProgressListener.unloadListener();
  544.     processedTab.showcaseProgressListener = undefined;
  545.   }
  546.  
  547.   if (processedTab.showcaseTabEventListener) {
  548.     try {
  549.       processedTab.targetTab.removeEventListener("resize", processedTab.showcaseTabEventListener, false);
  550.       processedTab.targetTab.removeEventListener("load", processedTab.showcaseTabEventListener, true);
  551.       if (thumbnailShowLabels) {
  552.         processedTab.tabHeader.removeEventListener("DOMAttrModified", processedTab.showcaseTabEventListener, false);
  553.       }
  554.       if (updateThumbnailWhenScroll) {
  555.         processedTab.targetTab.removeEventListener("scroll", processedTab.showcaseTabEventListener, true);
  556.       }
  557.     } catch (e) {}
  558.     processedTab.showcaseTabEventListener = undefined;
  559.   }
  560.   
  561.   if (processedTab.showcaseCanvas) {
  562.     processedTab.showcaseCanvas.width = 0;
  563.     processedTab.showcaseCanvas.height = 0;
  564.     processedTab.showcaseCanvas.showcaseCanvasBox = undefined;
  565.     processedTab.showcaseCanvas = undefined;
  566.   }
  567.   
  568.   processedTab.targetTab = undefined;
  569.   processedTab.targetTabWindow = undefined;
  570.   processedTab.tabHeader = undefined;
  571.  
  572.   if (tabWindow.processedTabs) {
  573.     var position = tabWindow.processedTabs.indexOf(processedTab);
  574.     if (position > -1) {
  575.       removeElementAt(tabWindow.processedTabs, position);
  576.     }
  577.   }
  578.  
  579.   if (selectTimerTarget == processedTab) {
  580.     selectTimer.cancel();
  581.     selectTimerTarget = null;
  582.   }
  583.   } catch (e) { alert("unlinkProcessedTab: " + e); }
  584. }
  585.  
  586. function setTabColor(tab, tabDocument) {
  587.   if (isNewLayout) {
  588.     tab.style.setProperty('background-color', showcaseCustomBackgroundColor, '');
  589.     tab.style.setProperty('color', showcaseCustomTitleColor, '');
  590.   } else {
  591.     var style = "-moz-appearance: none !important; color: " + showcaseCustomTitleColor + " !important;";
  592.     // background: " + showcaseCustomBackgroundColor + " !important;";
  593.     tabOldStyle = tab.getAttribute("style");
  594.     tab.setAttribute("style",  tabOldStyle + style);
  595.     var nodes = tabDocument.getAnonymousNodes(tab);
  596.     for (var i=0; i < nodes.length; i++)
  597.       nodes[i].style.setProperty('background-color', showcaseCustomBackgroundColor, '');
  598.   }
  599. }
  600.  
  601. function restoreTabColor(tab, tabDocument) {
  602.   if (isNewLayout) {
  603.     tab.style.removeProperty('background-color', showcaseCustomBackgroundColor, '');
  604.     tab.style.removeProperty('color', showcaseCustomTitleColor, '');
  605.   } else {
  606.     tab.setAttribute("style", tabOldStyle);
  607.     var nodes = tabDocument.getAnonymousNodes(tab);
  608.     for (var i=0; i < nodes.length; i++)
  609.       nodes[i].style.removeProperty ('background-color');
  610.   }
  611. }
  612.  
  613.  
  614. function updateBorders(targetProcessedWindow) {
  615.   // Get selected tab
  616.   var tabbrowser = targetProcessedWindow.targetWindow.getBrowser();
  617.   var tabs = tabbrowser.mTabContainer.childNodes;
  618.   var selectedTab = tabbrowser.getBrowserForTab(tabs[tabbrowser.mTabContainer.selectedIndex]);
  619.   
  620.   var multipleWindows = (processedWindows.length > 1);
  621.  
  622.   // Iterate array
  623.   for (var c=0; c<targetProcessedWindow.processedTabs.length; c++) {
  624.     var processedTab = targetProcessedWindow.processedTabs[c];
  625.     
  626.     if (multipleWindows && coloredThumbnailsForMultipleWindows) {
  627.       if (processedTab.targetTab == selectedTab) {
  628.         processedTab.showcaseCanvasBox.setAttribute("selectedtab", "true");
  629.       } else {
  630.         processedTab.showcaseCanvasBox.removeAttribute("selectedtab");
  631.       }
  632.       processedTab.showcaseCanvasSubBox.setAttribute("class", "coloredThumbnailBox" + targetProcessedWindow.showcaseColor);
  633.     } else {
  634.       if (processedTab.targetTab == selectedTab) {
  635.         processedTab.showcaseCanvasBox.setAttribute("selectedtab", "true");
  636.       } else {
  637.         processedTab.showcaseCanvasBox.removeAttribute("selectedtab");
  638.       }
  639.       processedTab.showcaseCanvasSubBox.setAttribute("class", "thumbnailBox");
  640.     }
  641.   }
  642. }
  643.  
  644. function updateTabBorder(processedTab, targetWindow) {
  645.   // Get selected tab
  646.   var tabbrowser = targetWindow.targetWindow.getBrowser();
  647.   var tabs = tabbrowser.mTabContainer.childNodes;
  648.   var selectedTab = tabbrowser.getBrowserForTab(tabs[tabbrowser.mTabContainer.selectedIndex]);
  649.   
  650.   var multipleWindows = (processedWindows.length > 1);
  651.   if (multipleWindows && coloredThumbnailsForMultipleWindows) {
  652.     if (processedTab.targetTab == selectedTab) {
  653.       processedTab.showcaseCanvasBox.setAttribute("selectedtab", "true");
  654.     } else {
  655.       processedTab.showcaseCanvasBox.removeAttribute("selectedtab");
  656.     }
  657.     processedTab.showcaseCanvasSubBox.setAttribute("class", "coloredThumbnailBox" + targetWindow.showcaseColor);
  658.   } else {
  659.     if (processedTab.targetTab == selectedTab) {
  660.       processedTab.showcaseCanvasBox.setAttribute("selectedtab", "true");
  661.     } else {
  662.       processedTab.showcaseCanvasBox.removeAttribute("selectedtab");
  663.     }
  664.     processedTab.showcaseCanvasSubBox.setAttribute("class", "thumbnailBox");
  665.   }
  666. }
  667.  
  668. function checkWindow(targetWindow, attempts) {
  669.   try {
  670.     if (linkWindow(targetWindow)) {
  671.       updateTitle();
  672.       setTimeout(refreshContent, 0);
  673.     }
  674.   } catch (e) {
  675.     // Window not ready, try again later...
  676.     if (attempts > 0) {
  677.       setTimeout(checkWindow, 100, targetWindow, --attempts);
  678.     } else if (processedWindows.length < 1) {
  679.       document.getElementById("emptyMessage").setAttribute("hidden", false);
  680.     }
  681.  
  682.   }
  683. }
  684.  
  685. function isWindowProcessed(targetWindow) {
  686.   var found = false;
  687.  
  688.   for (var c=0; (c<processedWindows.length)&&!found; c++) {
  689.     if (processedWindows[c].targetWindow == targetWindow) {
  690.       found = true;
  691.     }
  692.   }
  693.  
  694.   return found;
  695. }
  696.  
  697. function getProcessedWindowForWindow(targetWindow) {
  698.   var foundProcessedWindow;
  699.  
  700.   for (var c=0; (c<processedWindows.length)&&!foundProcessedWindow; c++) {
  701.     if (processedWindows[c].targetWindow == targetWindow) {
  702.       foundProcessedWindow = processedWindows[c];
  703.     }
  704.   }
  705.  
  706.   return foundProcessedWindow;
  707. }
  708.  
  709. function removeProcessedWindowForWindow(targetWindow) {
  710.   var found = false;
  711.  
  712.   for (var c=0; (c<processedWindows.length)&&!found; c++) {
  713.     if (processedWindows[c].targetWindow == targetWindow) {
  714.       removeElementAt(processedWindow, c);
  715.       found = true;
  716.     }
  717.   }
  718.   
  719.   return found;
  720. }
  721.  
  722. function linkWindow(targetWindow) {
  723.   if (!isWindowProcessed(targetWindow)) {
  724.       var tabbrowser = targetWindow.getBrowser();
  725.       var currentProcessedWindow = new ProcessedWindow(targetWindow);
  726.     // Assign window color
  727.     currentProcessedWindow.showcaseColor = windowCurrentColor;
  728.     windowCurrentColor++;
  729.     if (windowCurrentColor > NUMBER_BORDER_COLORS)
  730.       windowCurrentColor = 1;
  731.       
  732.       // Add listeners to tabsDOMNodeInserted
  733.       var tabsChangeListener = new TabsChangeListener(currentProcessedWindow, this);
  734.       tabbrowser.tabContainer.addEventListener("select", tabsChangeListener, false);
  735.       tabbrowser.tabContainer.addEventListener("DOMNodeInserted", tabsChangeListener, false);
  736.       tabbrowser.tabContainer.addEventListener("DOMNodeRemoved", tabsChangeListener, false); 
  737.       currentProcessedWindow.showcaseTabsChangeListener = tabsChangeListener;
  738.  
  739.       var tabs = tabbrowser.mTabContainer.childNodes;
  740.       var totalTabs = tabs.length;
  741.       var selectedTab = tabbrowser.getBrowserForTab(tabs[tabbrowser.mTabContainer.selectedIndex]);
  742.  
  743.       currentProcessedWindow.showcaseLastGoodWidth = selectedTab.contentWindow.innerWidth;
  744.       currentProcessedWindow.showcaseLastGoodHeight = selectedTab.contentWindow.innerHeight;
  745.  
  746.       // link current tabs
  747.       for (var j = 0; j< totalTabs; j++) {
  748.         var targetTab = tabbrowser.getBrowserForTab(tabs[j]);
  749.         if (targetTab.contentWindow && (!targetTab.contentWindow.isShowcaseWindow && (!targetTab.contentWindow.wrappedJSObject || !targetTab.contentWindow.wrappedJSObject.isShowcaseWindow))) {
  750.           var currentProcessedTab = new ProcessedTab(targetTab);
  751.           var newThumbnail = createThumbnail(tabs[j], currentProcessedTab, tabbrowser, currentProcessedWindow);
  752.  
  753.           // Cache
  754.           if (!currentProcessedTab.showcaseIETab && !currentProcessedTab.showcaseBlank && !currentProcessedTab.showcaseEmbedded) {
  755.             if (targetWindow.ShowcaseCache.currentShowcases.length > 0) {
  756.               // Get the biggest one
  757.               var bestShowcase = targetWindow.ShowcaseCache.currentShowcases[0];
  758.               
  759.               if (targetWindow.ShowcaseCache.currentShowcases.length > 1) {
  760.                 for (var c=0; c<targetWindow.ShowcaseCache.currentShowcases.length; c++) {
  761.                   var targetShowcase = targetWindow.ShowcaseCache.currentShowcases[c];
  762.                   if ((targetShowcase.thumbWidth > bestShowcase.thumbWidth) && (targetShowcase.thumbHeight > bestShowcase.thumbHeight)) {
  763.                     bestShowcase = targetShowcase;
  764.                   }
  765.                 }
  766.               }
  767.  
  768.               var remoteCanvas = bestShowcase.getProcessedWindowForWindow(targetWindow).processedTabs[currentProcessedWindow.processedTabs.length].showcaseCanvas;
  769.               if (remoteCanvas) {
  770.                 currentProcessedTab.showcaseCanvas.width = remoteCanvas.width;
  771.                 currentProcessedTab.showcaseCanvas.height = remoteCanvas.height; 
  772.                 var ctx = currentProcessedTab.showcaseCanvas.getContext("2d");
  773.                 ctx.drawImage(remoteCanvas, 0, 0, currentProcessedTab.showcaseCanvas.width, currentProcessedTab.showcaseCanvas.height);
  774.                 currentProcessedTab.showcaseCanvas.showcasePainted = true;
  775.               }
  776.             } else if (currentProcessedTab.targetTab.showcaseCache) {
  777.               var cache = currentProcessedTab.targetTab.showcaseCache;
  778.               if ((cache.thumb) && (!cache.waitingRepaint)) {
  779.                 currentProcessedTab.showcaseCanvas.width = cache.thumb.width;
  780.                 currentProcessedTab.showcaseCanvas.height = cache.thumb.height; 
  781.                 var ctx = currentProcessedTab.showcaseCanvas.getContext("2d");
  782.                 //var oriCtx = cache.thumb.getContext("2d");
  783.                 ctx.drawImage(cache.thumb, 0, 0, currentProcessedTab.showcaseCanvas.width, currentProcessedTab.showcaseCanvas.height);
  784.                 currentProcessedTab.showcaseCanvas.showcasePainted = true;
  785.               }
  786.             }
  787.           }
  788.  
  789.           // insert in document
  790.           showcaseBox.insertBefore(newThumbnail, selectionBox);
  791.  
  792.           currentProcessedWindow.processedTabs.push(currentProcessedTab);
  793.  
  794.           if (thumbnailBorderWidth < 0) {
  795.             /*
  796.             var showcaseCanvasBox = document.getBoxObjectFor(currentProcessedTab.showcaseCanvas);
  797.             if (showcaseCanvasBox) {
  798.               thumbnailBorderWidth = currentProcessedTab.showcaseCanvasBox.boxObject.width - showcaseCanvasBox.width;
  799.               thumbnailBorderHeight = currentProcessedTab.showcaseCanvasBox.boxObject.height - showcaseCanvasBox.height;
  800.             } else {
  801.               thumbnailBorderWidth = 3;
  802.               thumbnailBorderHeight = 3;
  803.             }
  804.             */
  805.             var externalBoxWidth = window.getComputedStyle(currentProcessedTab.showcaseCanvasBox, "width").width;
  806.             externalBoxWidth = externalBoxWidth.replace(/px/, "");
  807.             var externalBoxHeight = window.getComputedStyle(currentProcessedTab.showcaseCanvasBox, "height").height;
  808.             externalBoxHeight = externalBoxHeight.replace(/px/, "");
  809.  
  810.             var internalBoxWidth = window.getComputedStyle(currentProcessedTab.showcaseCanvas, "width").width;
  811.             internalBoxWidth = internalBoxWidth.replace(/px/, "");
  812.             var internalBoxHeight = window.getComputedStyle(currentProcessedTab.showcaseCanvas, "height").height;
  813.             internalBoxHeight = internalBoxHeight.replace(/px/, "");
  814.  
  815.             thumbnailBorderWidth = externalBoxWidth - internalBoxWidth;
  816.             thumbnailBorderHeight = externalBoxHeight - internalBoxHeight;
  817.  
  818.             if (thumbnailBorderWidth < 0) thumbnailBorderWidth = 0;
  819.             if (thumbnailBorderHeight < 0) thumbnailBorderHeight = 0;
  820.  
  821.             // Padding and border are not being computed...
  822.             // Add the padding.
  823.             // FIXME. This is a hack, there must be a better way to handle this.
  824.             if (thumbnailLabelStyle == 0) {
  825.               thumbnailBorderWidth += 8;
  826.               thumbnailBorderHeight += 8;
  827.             } else {
  828.               thumbnailBorderWidth += 10;
  829.               thumbnailBorderHeight += 10;
  830.             }
  831.           }
  832.         }
  833.       }
  834.     processedWindows.push(currentProcessedWindow);
  835.  
  836.     // Register as window observer
  837.     targetWindow.ShowcaseCache.addShowcase(window);
  838.  
  839.     return true;
  840.   }
  841.   return false;
  842. }
  843.  
  844. // To unlink a window
  845. function unlinkProcessedWindow(targetProcessedWindow, cacheMode) {
  846.   try {
  847.     var tabbrowser = targetProcessedWindow.targetWindow.getBrowser();
  848.  
  849.     // Remove listeners to tabsDOMNodeInserted
  850.     tabbrowser.tabContainer.removeEventListener("select", targetProcessedWindow.showcaseTabsChangeListener, false); 
  851.     tabbrowser.tabContainer.removeEventListener("DOMNodeInserted", targetProcessedWindow.showcaseTabsChangeListener, false); 
  852.     tabbrowser.tabContainer.removeEventListener("DOMNodeRemoved", targetProcessedWindow.showcaseTabsChangeListener, false); 
  853.     
  854.     // Unlink tabs
  855.     if (targetProcessedWindow.processedTabs.length > 0) {
  856.       for (var c=targetProcessedWindow.processedTabs.length-1; c>=0; c--) {
  857.         var targetProcessedTab = targetProcessedWindow.processedTabs[c];
  858.         if (targetProcessedTab.showcaseCanvasBox) {
  859.           if (targetProcessedTab.targetTab.showcaseCache) {
  860.             if (cacheMode == CACHEMODE_CLEAR) {
  861.               targetProcessedTab.targetTab.showcaseCache.thumb = null;
  862.             } else if ((cacheMode == CACHEMODE_UPDATE) && (targetProcessedTab.targetTab.showcaseCache)) {
  863.               if (targetProcessedWindow.targetWindow.ShowcaseCache.currentShowcases.length < 2) {
  864.                 if (!targetProcessedTab.targetTab.showcaseCache.thumb) {
  865.                   targetProcessedTab.targetTab.showcaseCache.createThumbnail();
  866.                 }
  867.                 var targetThumb = targetProcessedTab.targetTab.showcaseCache.thumb;
  868.                 targetThumb.width = targetProcessedTab.showcaseCanvas.width;
  869.                 targetThumb.height  = targetProcessedTab.showcaseCanvas.height;
  870.                 var ctx = targetThumb.getContext("2d");
  871.                 ctx.drawImage(targetProcessedTab.showcaseCanvas, 0, 0, targetThumb.width, targetThumb.height);
  872.               }
  873.             }
  874.           }
  875.           showcaseBox.removeChild(targetProcessedTab.showcaseCanvasBox);
  876.           unlinkProcessedTab(targetProcessedTab, targetProcessedWindow );
  877.         }
  878.       }
  879.     }
  880.  
  881.     // Unregister
  882.     targetProcessedWindow.targetWindow.ShowcaseCache.removeShowcase(window);
  883.  
  884.     var position = processedWindows.indexOf(targetProcessedWindow);
  885.     if (position > -1) {
  886.       removeElementAt(processedWindows, position);
  887.     }
  888.   } catch (e) {
  889.     setTimeout(alert, 0, "UnlinkProcessedWindow - " + e);
  890.   }
  891. }
  892.  
  893. function unlinkShowcase(cacheMode) {
  894.   // Reset tab style
  895.   if (showcaseCustomColors) {
  896.     showcaseBox.style.backgroundColor = showcaseOldBackgroundColor;
  897.     
  898.     if ((window.top != topWindow) && (tabColorizeLabel)) {
  899.       // We're a tab, set the style...
  900.       var tabbrowser = topWindow.getBrowser();
  901.       var l = tabbrowser.tabContainer.childNodes.length;
  902.       for (var i = 0; i < l; i++) {
  903.         var tab = tabbrowser.mTabContainer.childNodes[i];
  904.         if (tab.linkedBrowser.contentWindow == window) {
  905.           // We're in a tab
  906.           restoreTabColor(tab, topWindow.document);
  907.         }
  908.       }
  909.     }
  910.   }
  911.  
  912.   // Unload all pending variables
  913.   try {
  914.     unregisterObservers();
  915.     while (processedWindows.length > 0) {
  916.       unlinkProcessedWindow(processedWindows[0], cacheMode);
  917.     }
  918.  
  919.     removeAllElements(currentAnimations);
  920.     removeAllElements(pendingThumbnails);
  921.  
  922.     window.removeEventListener("resize", sizeChanged, false);
  923.     showcaseContentVertical.removeEventListener("overflow", sizeChanged, false);
  924.     showcaseContentVertical.removeEventListener("underflow", sizeChanged, false);
  925.     showcaseContentVertical.removeEventListener("DOMMouseScroll", handleMouseWheel, true);
  926.   } catch (e) {
  927.     alert("unlinkShowcase - " + e);
  928.   }
  929.   
  930.   // End selection if necessary
  931.   endSelection();
  932.  
  933.   // Cancel selections
  934.   if (selectTimer) {
  935.     selectTimer.cancel();
  936.     selectTimer = undefined;
  937.     selectTimerTarget = undefined;
  938.   }
  939.  
  940.   // Show tab bar if necessary
  941.   if (hideTabBar) {
  942.     var tabbrowser = window.top.getBrowser();
  943.     
  944.     var tabstrip = window.top.document.getAnonymousElementByAttribute(tabbrowser,"class","tabbrowser-tabs");
  945.     
  946.     if (tabstrip) {
  947.       tabstrip.collapsed=false;
  948.     }
  949.   }
  950.  
  951.   if (showcaseCloseWhenParentFocus) {
  952.     try {
  953.       window.opener.removeEventListener("focus", showcaseParentGotFocus, true);
  954.     } catch (e) {}
  955.   }
  956.  
  957. //  window.removeEventListener("focus", showcaseGainedFocus, false);
  958.   window.removeEventListener("blur", showcaseLostFocus, false);
  959.  
  960.   return true; 
  961. }
  962.  
  963. var ShowcasePrefObserver = 
  964. {
  965.   prefObserver : {
  966.     refreshTimer : null,
  967.  
  968.     observe: function(subject, topic, data) {
  969.     // subject is the nsIPrefBranch we're observing (after appropriate QI)
  970.     // data is the name of the pref that's been changed (relative to subject)
  971.       if(topic == "nsPref:changed") {
  972.         if ((data != "extensions.showcase.windowLastX") &&
  973.             (data != "extensions.showcase.windowLastY") &&
  974.             (data != "extensions.showcase.windowLastWidth") &&
  975.             (data != "extensions.showcase.windowLastHeight") &&
  976.             (data != "extensions.showcase.windowLastRelativeX") &&
  977.             (data != "extensions.showcase.windowLastRelativeY")) {
  978.           if (this.refreshTimer == null) {
  979.             this.refreshTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
  980.           }
  981.           this.refreshTimer.cancel();
  982.           this.refreshTimer.initWithCallback(this, 100, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
  983.         }
  984.       }
  985.     },
  986.  
  987.     QueryInterface : function (aIID) {
  988.       if (aIID.equals(Components.interfaces.nsIObserver) || 
  989.       aIID.equals(Components.interfaces.nsITimerCallback) ||
  990.       aIID.equals(Components.interfaces.nsISupports) ||
  991.       aIID.equals(Components.interfaces.nsISupportsWeakReference))
  992.         return this;
  993.       throw Components.results.NS_NOINTERFACE;
  994.     },
  995.  
  996.     notify: function(timer) {
  997.       setTimeout(refreshScreen, 0);
  998.     }
  999.   },
  1000.  
  1001.   addPrefObserver : function () {
  1002.     if (!gPref) return;
  1003.     gPref.addObserver("extensions.showcase.", ShowcasePrefObserver.prefObserver, true);
  1004.   },
  1005.  
  1006.   removePrefObserver : function () {
  1007.     if (ShowcasePrefObserver.prefObserver.refreshTimer) {
  1008.       ShowcasePrefObserver.prefObserver.refreshTimer.cancel();
  1009.       ShowcasePrefObserver.prefObserver.refreshTimer = null;
  1010.     }
  1011.  
  1012.     if (!gPref) return;
  1013.     gPref.removeObserver("extensions.showcase.", ShowcasePrefObserver.prefObserver);
  1014.   }
  1015. }
  1016.  
  1017. function registerObservers() {
  1018.   // We want to observe click actions in our window
  1019.   addEventListener("mouseup", mouseUpWindow, (topWindow != window));
  1020.   addEventListener("dblclick", mouseDblClickWindow, (topWindow != window));
  1021.   addEventListener("keydown", windowKeyDown, false);
  1022.   addEventListener("keyup", windowKeyUp, false);
  1023.  
  1024.   // Add selection listener
  1025.   showcaseBox.addEventListener("mousedown", selectionBoxStart, false);
  1026.   showcaseBox.addEventListener("mouseup", selectionBoxEnd, false);
  1027.   showcaseBox.addEventListener("mouseout", boxMouseOut, false);
  1028.   showcaseBox.addEventListener("mousemove", selectionBoxCheck, false);
  1029.   showcaseBox.addEventListener("keypress", showcaseBoxCheckKey, false);
  1030.  
  1031.   var watcherService =
  1032.     Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
  1033.       .getService(Components.interfaces.nsIWindowWatcher);
  1034.   watcherService.registerNotification(windowObserver);
  1035.  
  1036.   ShowcasePrefObserver.addPrefObserver();
  1037. }
  1038.  
  1039. function unregisterObservers() {
  1040.   // Unregister mouse listener
  1041.   removeEventListener("mouseup", mouseUpWindow, (topWindow != window));
  1042.   removeEventListener("dblclick", mouseDblClickWindow, (topWindow != window));
  1043.   removeEventListener("keydown", windowKeyDown, false);
  1044.   removeEventListener("keyup", windowKeyUp, false);
  1045.  
  1046.   // Add selection listener
  1047.   showcaseBox.removeEventListener("mousedown", selectionBoxStart, false);
  1048.   showcaseBox.removeEventListener("mouseup", selectionBoxEnd, false);
  1049.   showcaseBox.removeEventListener("mouseout", boxMouseOut, false);
  1050.   showcaseBox.removeEventListener("mousemove", selectionBoxCheck, false);
  1051.   showcaseBox.removeEventListener("keypress", showcaseBoxCheckKey, false);
  1052.  
  1053.   var watcherService =
  1054.     Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
  1055.       .getService(Components.interfaces.nsIWindowWatcher);
  1056.   watcherService.unregisterNotification(windowObserver);
  1057.  
  1058.   ShowcasePrefObserver.removePrefObserver();
  1059. }
  1060.  
  1061. function loadContextualSettings() {
  1062.   // Load showcase contextual settings
  1063.   var prefsService = Components.classes["@mozilla.org/preferences-service;1"].
  1064.                 getService(Components.interfaces.nsIPrefService);
  1065.   var prefs = prefsService.getBranch("extensions.showcase.");
  1066.  
  1067.   // Load contextual menu actions
  1068.   contextualActionOpen = prefs.getBoolPref("contextualActionOpen");
  1069.   contextualActionShowcaseThis = prefs.getBoolPref("contextualActionShowcaseThis");
  1070.   contextualActionBack = prefs.getBoolPref("contextualActionBack");
  1071.   contextualActionForward = prefs.getBoolPref("contextualActionForward");
  1072.   contextualActionReload = prefs.getBoolPref("contextualActionReload");
  1073.   contextualActionStop = prefs.getBoolPref("contextualActionStop");
  1074.   contextualActionDuplicateTab = prefs.getBoolPref("contextualActionDuplicateTab");
  1075.   contextualActionDuplicateSelected = prefs.getBoolPref("contextualActionDuplicateSelected");
  1076.   contextualActionMoveTab = prefs.getBoolPref("contextualActionMoveTab");
  1077.   contextualActionMergeSelected = prefs.getBoolPref("contextualActionMergeSelected");
  1078.   contextualActionBookmarkPage = prefs.getBoolPref("contextualActionBookmarkPage");
  1079.   contextualActionBookmarkSelected = prefs.getBoolPref("contextualActionBookmarkSelected");
  1080.   contextualActionSavePage = prefs.getBoolPref("contextualActionSavePage");
  1081.   contextualActionSendPage = prefs.getBoolPref("contextualActionSendPage");
  1082.   contextualActionPrint = prefs.getBoolPref("contextualActionPrint");
  1083.   contextualActionViewSource = prefs.getBoolPref("contextualActionViewSource");
  1084.   contextualActionPageInfo = prefs.getBoolPref("contextualActionPageInfo");
  1085.   contextualActionCloseOther = prefs.getBoolPref("contextualActionCloseOther");
  1086.   contextualActionClose = prefs.getBoolPref("contextualActionClose");
  1087.   contextualActionCloseTab = prefs.getBoolPref("contextualActionCloseTab");
  1088.   contextualActionCloseWindow = prefs.getBoolPref("contextualActionCloseWindow");
  1089.  
  1090.   loadedContextualSettings = true;
  1091. }
  1092.  
  1093. function loadSettings() {
  1094.   // Load showcase settings
  1095.   var prefsService = Components.classes["@mozilla.org/preferences-service;1"].
  1096.                 getService(Components.interfaces.nsIPrefService);
  1097.  
  1098.   var prefsRoot = prefsService.getBranch(null);
  1099.  
  1100.   browserChromeURL = prefsRoot.getCharPref("browser.chromeURL");
  1101.  
  1102.   var prefs = prefsService.getBranch("extensions.showcase.");
  1103.   
  1104.   coloredThumbnailsForMultipleWindows = prefs.getBoolPref("coloredThumbnailsForMultipleWindows");
  1105.   paintThumbnailsAfterLoading = prefs.getBoolPref("paintThumbnailsAfterLoading");
  1106.   paintSelectedTabsFirst = prefs.getBoolPref("paintSelectedTabsFirst");
  1107.   thumbnailActiveAnimation = prefs.getBoolPref("thumbnailActiveAnimation");
  1108.   animationFrames = prefs.getIntPref("animationFrames");
  1109.   thumbnailIdleSizeFactor = parseFloat(prefs.getCharPref("thumbnailIdleSizeFactor"));
  1110.   thumbnailActiveSizeFactor = parseFloat(prefs.getCharPref("thumbnailActiveSizeFactor"));
  1111.   thumbnailShowLabels = prefs.getBoolPref("thumbnailShowLabels");
  1112.   thumbnailLabelStyle = prefs.getIntPref("thumbnailLabelStyle");
  1113.   windowAttributeFullScreen = prefs.getBoolPref("windowAttributeFullScreen");
  1114.   windowAttributeMaximized = prefs.getBoolPref("windowAttributeMaximized");
  1115.   windowAttributeTranslucent = prefs.getBoolPref("windowAttributeTranslucent");
  1116.   updateThumbnailWhenContentLoaded = prefs.getBoolPref("updateThumbnailWhenContentLoaded");
  1117.   updateThumbnailWhenScroll = prefs.getBoolPref("updateThumbnailWhenScroll");
  1118.   updateThumbnailWhenContentChanges = prefs.getBoolPref("updateThumbnailWhenContentChanges");
  1119.   updateThumbnailWhenTitleChanges = prefs.getBoolPref("updateThumbnailWhenTitleChanges");
  1120.   limitContentChangeUpdates = prefs.getBoolPref("limitContentChangeUpdates");
  1121.   limitContentChangeUpdatesTime = prefs.getIntPref("limitContentChangeUpdatesTime");
  1122.   leftClickAction = prefs.getIntPref("leftClickAction");
  1123.   middleClickAction = prefs.getIntPref("middleClickAction");
  1124.   rightClickAction = prefs.getIntPref("rightClickAction");
  1125.   doubleClickOpen = prefs.getBoolPref("doubleClickOpen");
  1126.   thumbnailTooltipTitle = prefs.getBoolPref("thumbnailTooltipTitle");
  1127.   thumbnailTooltipURL = prefs.getBoolPref("thumbnailTooltipURL");
  1128.   closeLastTabKeepOpen = prefs.getBoolPref("closeLastTabKeepOpen");
  1129.   dragDropExclude = prefs.getIntPref("dragDropExclude");
  1130.   zoomScrollIncrement = prefs.getIntPref("zoomScrollIncrement");
  1131.  
  1132.   thumbnailBackButton = prefs.getBoolPref("thumbnailBackButton");
  1133.   thumbnailForwardButton = prefs.getBoolPref("thumbnailForwardButton");
  1134.   thumbnailStopButton = prefs.getBoolPref("thumbnailStopButton");
  1135.   thumbnailReloadButton = prefs.getBoolPref("thumbnailReloadButton");
  1136.   thumbnailHistoryButton = prefs.getBoolPref("thumbnailHistoryButton");
  1137.   
  1138.   newThumbnailStyle = prefs.getBoolPref("newThumbnailStyle");
  1139.  
  1140.   if (thumbnailActiveAnimation && (thumbnailIdleSizeFactor > thumbnailActiveSizeFactor)) {
  1141.     // if idle size is bigger than active size, then we've a mistake here... deactivate animation
  1142.     thumbnailActiveAnimation = false;
  1143.   }
  1144.  
  1145.   if (window != window.top) {
  1146.     // Sidebar
  1147.     showcaseCustomColors = prefs.getBoolPref("sidebarCustomColors");
  1148.     showcaseCustomBackgroundColor = prefs.getCharPref("sidebarCustomBackgroundColor");
  1149.     showcaseCloseWhenBlur = false;
  1150.     showcaseCloseWhenParentFocus = false;
  1151.     showcaseCloseWhenSelect = prefs.getBoolPref("sidebarCloseWhenSelect");
  1152.     showcaseCloseWhenZeroThumbnails = false;
  1153.     showTitleStats = prefs.getBoolPref("sidebarShowTitleStats");
  1154.     scrollType = prefs.getIntPref("sidebarScrollType");
  1155.     thumbnailPreferredMinimumSize = prefs.getIntPref("sidebarThumbnailPreferredMinimumSize");
  1156.     alwaysShowScrollbar = prefs.getBoolPref("sidebarAlwaysShowScrollbar");
  1157.     if (globalMode) {
  1158.       showOnlyCurrentByDefault = prefs.getBoolPref("sidebarShowOnlyCurrentByDefault");
  1159.     }
  1160.     selectWhenMouseOver = prefs.getBoolPref("sidebarSelectWhenMouseOver");
  1161.     selectWhenMouseOverDelay = prefs.getIntPref("sidebarSelectWhenMouseOverDelay");
  1162.     hideTabBar = prefs.getBoolPref("sidebarHideTabBar");
  1163.     tabFlipping = prefs.getBoolPref("sidebarTabFlipping");
  1164.     findBarMode = prefs.getIntPref("sidebarFindBarMode");
  1165.     zoomFitsScreen = prefs.getBoolPref("sidebarZoomFitsScreen");
  1166.     selectWhenOpen = prefs.getBoolPref("sidebarSelectWhenOpen");
  1167.     doubleClickAction = prefs.getIntPref("sidebarDoubleClickAction");
  1168.     focusShowcase = prefs.getBoolPref("sidebarFocusShowcase");
  1169.   } else if (window.top != topWindow) {
  1170.     // Tab
  1171.     showcaseCustomColors = prefs.getBoolPref("tabCustomColors");
  1172.     showcaseCustomTitleColor = prefs.getCharPref("tabCustomTitleColor");
  1173.     showcaseCustomBackgroundColor = prefs.getCharPref("tabCustomBackgroundColor");
  1174.     showcaseCloseWhenBlur = prefs.getBoolPref("tabCloseWhenBlur");
  1175.     showcaseCloseWhenParentFocus = false;
  1176.     showcaseCloseWhenSelect = prefs.getBoolPref("tabCloseWhenSelect");
  1177.     showcaseCloseWhenZeroThumbnails = prefs.getBoolPref("tabCloseWhenZeroThumbnails");
  1178.     showTitleStats = prefs.getBoolPref("tabShowTitleStats");
  1179.     scrollType = prefs.getIntPref("tabScrollType");
  1180.     thumbnailPreferredMinimumSize = prefs.getIntPref("tabThumbnailPreferredMinimumSize");
  1181.     alwaysShowScrollbar = prefs.getBoolPref("tabAlwaysShowScrollbar");
  1182.     if (globalMode) {
  1183.       showOnlyCurrentByDefault = prefs.getBoolPref("tabShowOnlyCurrentByDefault");
  1184.     }
  1185.     synchFindBar = prefs.getBoolPref("tabSynchFindBar");
  1186.     tabColorizeLabel = prefs.getBoolPref("tabColorizeLabel");
  1187.     tabFlipping = prefs.getBoolPref("tabTabFlipping");
  1188.     zoomFitsScreen = prefs.getBoolPref("tabZoomFitsScreen");
  1189.     selectWhenOpen = prefs.getBoolPref("tabSelectWhenOpen");
  1190.     doubleClickAction = prefs.getIntPref("tabDoubleClickAction");
  1191.     focusShowcase = prefs.getBoolPref("tabFocusShowcase");
  1192.   } else {
  1193.     // Window
  1194.     showcaseCustomColors = prefs.getBoolPref("windowCustomColors");
  1195.     showcaseCustomBackgroundColor = prefs.getCharPref("windowCustomBackgroundColor");
  1196.     showcaseCloseWhenBlur = prefs.getBoolPref("windowCloseWhenBlur");
  1197.     showcaseCloseWhenParentFocus = prefs.getBoolPref("windowCloseWhenParentFocus");
  1198.     showcaseCloseWhenSelect = prefs.getBoolPref("windowCloseWhenSelect");
  1199.     showcaseCloseWhenZeroThumbnails = prefs.getBoolPref("windowCloseWhenZeroThumbnails");
  1200.     showTitleStats = prefs.getBoolPref("windowShowTitleStats");
  1201.     scrollType = prefs.getIntPref("windowScrollType");
  1202.     thumbnailPreferredMinimumSize = prefs.getIntPref("windowThumbnailPreferredMinimumSize");
  1203.     alwaysShowScrollbar = prefs.getBoolPref("windowAlwaysShowScrollbar");
  1204.     if (globalMode) {
  1205.       showOnlyCurrentByDefault = prefs.getBoolPref("windowShowOnlyCurrentByDefault");
  1206.     }
  1207.     tabFlipping = prefs.getBoolPref("windowTabFlipping");
  1208.     zoomFitsScreen = prefs.getBoolPref("windowZoomFitsScreen");
  1209.     selectWhenOpen = prefs.getBoolPref("windowSelectWhenOpen");
  1210.     doubleClickAction = prefs.getIntPref("windowDoubleClickAction");
  1211.     focusShowcase = prefs.getBoolPref("windowFocusShowcase");
  1212.   }
  1213.  
  1214.   // Detection settings
  1215.   detectBlank = prefs.getBoolPref("detectBlank");
  1216.   detectIETab = prefs.getBoolPref("detectIETab");
  1217.   detectPlugin = prefs.getBoolPref("detectPlugin");
  1218.   detectImage = prefs.getBoolPref("detectImage");
  1219.  
  1220.   if (detectImage) {
  1221.     imageThumbnailUpscale = prefs.getBoolPref("imageThumbnailUpscale");
  1222.   }
  1223.  
  1224.   // Rendering type
  1225.   renderingType = prefs.getIntPref("renderingType");
  1226.  
  1227.   // Scrolling
  1228.   verticalScrollbarWidth = prefs.getIntPref("verticalScrollbarWidth");
  1229.   horizontalScrollbarHeight = prefs.getIntPref("horizontalScrollbarHeight");
  1230.  
  1231.   // Special parameters
  1232.   useWindowZOrder = prefs.getBoolPref("useWindowZOrder");
  1233. }
  1234.  
  1235. function activateFullScreen() {
  1236.   if (windowAttributeMaximized) {
  1237.     window.maximize();
  1238.   }
  1239.   if (windowAttributeFullScreen) {
  1240.     window.fullScreen = true;
  1241.   }
  1242.   contentStartup(thumbnailActiveAnimation);
  1243. }
  1244.  
  1245. function contentStartup(startAnimationThread) {
  1246.   registerObservers();
  1247.  
  1248.   createContent();
  1249.  
  1250.   window.addEventListener("resize", sizeChanged, false);
  1251.   showcaseContentVertical.addEventListener("overflow", sizeChanged, false);
  1252.   showcaseContentVertical.addEventListener("underflow", sizeChanged, false);
  1253.   showcaseContentVertical.addEventListener("DOMMouseScroll", handleMouseWheel, true);
  1254.  
  1255.   // Start animation thread
  1256.   if (startAnimationThread) {
  1257.     setTimeout(animationThread, ANIMATION_INTERVAL);
  1258.   }
  1259.   
  1260.   // Hide tab bar if necessary
  1261.   if (hideTabBar) {
  1262.     var tabbrowser = window.top.getBrowser();
  1263.     
  1264.     var tabstrip = window.top.document.getAnonymousElementByAttribute(tabbrowser,"class","tabbrowser-tabs");
  1265.     
  1266.     if (tabstrip) {
  1267.       tabstrip.collapsed=true;
  1268.     }
  1269.   }
  1270. }
  1271.  
  1272. function showcaseCloseWindow() {
  1273.   if (window.top != window) {
  1274. /*
  1275.     if (!closingShowcase) {
  1276.       closingShowcase = true;
  1277.       unlinkShowcase();
  1278.     }
  1279. */
  1280.     // Sidebar
  1281.     if (originalGlobalMode) {
  1282.       window.top.toggleSidebar(SHOWCASE_SIDEBAR);
  1283.     } else {
  1284.       window.top.toggleSidebar(SHOWCASETHISWINDOW_SIDEBAR);
  1285.     }
  1286.   } else {
  1287.     window.close();
  1288.   }
  1289. }
  1290.  
  1291. function showcaseLostFocus(event) {
  1292.   if (event.originalTarget == window.document) {
  1293.     if (showcaseBox) {
  1294.       showcaseBox.setAttribute("windowFocused", "false");
  1295.     }
  1296.     if (showcaseCloseWhenBlur && !isWaitingRefocus) {
  1297.       showcaseCloseWindow();
  1298.     }
  1299.   }
  1300. }
  1301.  
  1302. function showcaseGainedFocus() {
  1303.   if (showcaseBox) {
  1304.     showcaseBox.setAttribute("windowFocused", "true");
  1305.   }
  1306. }
  1307.  
  1308. function showcaseBrowserStop() {
  1309.   try {
  1310.     const stopFlags = nsIWebNavigation.STOP_ALL;
  1311.     window.showcasePopupTab.targetTab.webNavigation.stop(stopFlags);
  1312.   }
  1313.   catch(ex) {
  1314.   }
  1315. }
  1316.  
  1317. function showcaseBrowserReloadSkipCache() {
  1318.   if (selectedTabs.length < 2) {
  1319.     showcasePopupTab.targetTab.webNavigation.reload(RELOAD_SKIP_CACHE_FLAGS);
  1320.   } else {
  1321.     for (var c=0; c<selectedTabs.length; c++) {
  1322.       var currentTab = selectedTabs[c].targetTab;
  1323.       var location;
  1324.       if (currentTab.currentURI) {
  1325.         location = currentTab.currentURI.spec;
  1326.       } else {
  1327.         location = "about:blank";
  1328.       }
  1329.  
  1330.       if ((location != "about:blank") && (location != "")) {
  1331.         currentTab.webNavigation.reload(RELOAD_SKIP_CACHE_FLAGS);
  1332.       }
  1333.     }
  1334.   }
  1335. }
  1336.  
  1337. function showcaseBrowserReload() {
  1338.   if (selectedTabs.length < 2) {
  1339.     showcasePopupTab.targetTab.webNavigation.reload(RELOAD_FLAGS);
  1340.   } else {
  1341.     for (var c=0; c<selectedTabs.length; c++) {
  1342.       var currentTab = selectedTabs[c].targetTab;
  1343.       var location;
  1344.       if (currentTab.currentURI) {
  1345.         location = currentTab.currentURI.spec;
  1346.       } else {
  1347.         location = "about:blank";
  1348.       }
  1349.  
  1350.       if ((location != "about:blank") && (location != "")) {
  1351.         currentTab.webNavigation.reload(RELOAD_FLAGS);
  1352.       }
  1353.     }
  1354.   }
  1355. }
  1356.  
  1357. function showcaseAddBookmark() {
  1358.   try {
  1359.     if ("addBookmarkForBrowser" in BookmarksUtils) { // SeaMonkey
  1360.       BookmarksUtils
  1361.       .addBookmarkForBrowser(window.showcasePopupTab.targetTab.webNavigation, true);
  1362.     }
  1363.     else {
  1364.     addBookmarkForBrowser(window.showcasePopupTab.targetTab.webNavigation, false);
  1365. }
  1366.   } catch (e) {
  1367.     alert(e);
  1368.   }
  1369. }
  1370.  
  1371. function showcaseBookmarkSelected() {
  1372.   if (isNewLayout) {
  1373.     var tabList = [];
  1374.     var seenURIs = [];
  1375.  
  1376.     for (var i = 0; i < selectedTabs.length; ++i) {
  1377.       var webNav = selectedTabs[i].targetTab.webNavigation;
  1378.       var uri = webNav.currentURI;
  1379.  
  1380.       // skip redundant entries
  1381.       if (uri.spec in seenURIs)
  1382.         continue;
  1383.  
  1384.       // add to the set of seen URIs
  1385.       seenURIs[uri.spec] = true;
  1386.       tabList.push(uri);
  1387.     }
  1388.     PlacesUIUtils.showMinimalAddMultiBookmarkUI(tabList);
  1389.   } else {
  1390.     var tabsInfo = [];
  1391.     var currentTabInfo = { name: "", url: "", charset: null };
  1392.   
  1393.     for (var i = 0; i < selectedTabs.length; ++i) {
  1394.       var webNav = selectedTabs[i].targetTab.webNavigation;
  1395.   
  1396.       var url = webNav.currentURI.spec;
  1397.       var name = "";
  1398.       var charSet, description;
  1399.       try {
  1400.         var doc = webNav.document;
  1401.         name = doc.title || url;
  1402.         charSet = doc.characterSet;
  1403.         description = BookmarksUtils.getDescriptionFromDocument(doc);
  1404.       } catch (e) {
  1405.         name = url;
  1406.       }
  1407.       tabsInfo[i] = { name: name, url: url, charset: charSet, description: description };
  1408.       if (i == 0)
  1409.         currentTabInfo = tabsInfo[0];
  1410.     }
  1411.     
  1412.     var dialogArgs = currentTabInfo;
  1413.   
  1414.     var showcaseBundle = document.getElementById("bundle_showcase");
  1415.   
  1416.     dialogArgs = { name: showcaseBundle.getString("bookmarkSelectedTabsDefault") };
  1417.     dialogArgs.bBookmarkAllTabs = true;
  1418.   
  1419.     dialogArgs.objGroup = tabsInfo;
  1420.     openDialog("chrome://browser/content/bookmarks/addBookmark2.xul", "",
  1421.                BROWSER_ADD_BM_FEATURES, dialogArgs);
  1422.     
  1423.   }
  1424. }
  1425.  
  1426. function showcaseSendLink() {
  1427.   var gHasIntegratedMailClient = ("@mozilla.org/messengercompose/composeparams;1" in Components.classes);
  1428.   var url = window.showcasePopupTab.targetTab.contentWindow.location.href;
  1429.   var title = window.showcasePopupTab.targetTab.contentWindow.document.title;
  1430.   try {
  1431.     if (!gHasIntegratedMailClient) {
  1432.       
  1433.       MailIntegration.sendMessage(url, title);
  1434.       
  1435.     }
  1436.     else {
  1437.         var params = Components.classes["@mozilla.org/messengercompose/composeparams;1"]
  1438.                                .createInstance(Components.interfaces.nsIMsgComposeParams);
  1439.         if (params)
  1440.         {
  1441.           params.composeFields = Components.classes['@mozilla.org/messengercompose/composefields;1']
  1442.                                            .createInstance(Components.interfaces.nsIMsgCompFields);
  1443.           if (params.composeFields)
  1444.           {
  1445.             params.composeFields.body = url;
  1446.             params.composeFields.subject = title;
  1447.             params.bodyIsLink = true;
  1448.             var composeService = Components.classes["@mozilla.org/messengercompose;1"]
  1449.                                            .getService(Components.interfaces.nsIMsgComposeService);
  1450.             if (composeService) {
  1451.               // it is possible you won't have a default identity
  1452.               // like if you've never launched mail before on a new profile.
  1453.               // see bug #196073
  1454.               try {
  1455.                 params.identity = composeService.defaultIdentity;
  1456.               }
  1457.               catch (ex) {
  1458.                 params.identity = null;
  1459.               }
  1460.               composeService.OpenComposeWindowWithParams(null, params);
  1461.             }
  1462.           }                                                                         
  1463.         }                                                                         
  1464.     }
  1465.   }
  1466.   catch (e) {
  1467.     alert(e);
  1468.   }
  1469. }
  1470.  
  1471. function showcasePrint() {
  1472.   try {
  1473.     window.showcasePopupTab.targetTab.contentWindow.print();
  1474.   } catch (e) {
  1475.     alert(e);
  1476.   }
  1477. }
  1478.  
  1479. function toggleShowOnlyCurrent() {
  1480.   showOnlyCurrent = !showOnlyCurrent;
  1481.   updateTitle();
  1482.  
  1483.   if (!showOnlyCurrent) {
  1484.     // Reset visibility
  1485.     for (var i = 0; i < processedWindows.length; i++) {
  1486.       var targetWindow =  processedWindows[i];
  1487.       for (var j = 0; j<targetWindow.processedTabs.length; j++) {
  1488.         var currentTab = targetWindow.processedTabs[j];
  1489.         currentTab.showcaseCanvasBox.hidden = false;
  1490.       }
  1491.     }
  1492.   }
  1493.  
  1494.   refreshContent();
  1495. }
  1496.  
  1497. function updateShowOnlyCurrent() {
  1498.   if (inZoomMode) {
  1499.     return;
  1500.   }
  1501.  
  1502.   // Set visibility
  1503.   for (var i = 0; i < processedWindows.length; i++) {
  1504.     var targetWindow =  processedWindows[i];
  1505.     var tabbrowser = targetWindow.targetWindow.getBrowser();
  1506.     var tabs = tabbrowser.mTabContainer.childNodes;
  1507.     var selectedTab = tabbrowser.getBrowserForTab(tabs[tabbrowser.mTabContainer.selectedIndex]);
  1508.  
  1509.     for (var j = 0; j<targetWindow.processedTabs.length; j++) {
  1510.       var currentTab = targetWindow.processedTabs[j];
  1511.       if (currentTab.targetTab != selectedTab) {
  1512.         currentTab.showcaseCanvasBox.hidden = true;
  1513.       } else {
  1514.         currentTab.showcaseCanvasBox.hidden = false;
  1515.       }
  1516.     }
  1517.   }
  1518. }
  1519.  
  1520. function openSelectedTab() {
  1521.   openTab(showcasePopupTab);
  1522. }
  1523.  
  1524. function closeOtherTabs() {
  1525.   // Create an array with all the possibilities
  1526.   var targetTabs = new Array();
  1527.  
  1528.   for (var c=0; (c<processedWindows.length); c++) {
  1529.     targetWindow = processedWindows[c];
  1530.     for (var d=0; (d<targetWindow.processedTabs.length); d++) {
  1531.       targetTabs.push(targetWindow.processedTabs[d]);
  1532.     }    
  1533.   }
  1534.  
  1535.   // Take out the selected ones
  1536.   for (var c=0; c<selectedTabs.length; c++) {
  1537.     var targetIndex = targetTabs.indexOf(selectedTabs[c]);
  1538.     if (targetIndex > -1) {
  1539.       removeElementAt(targetTabs, targetIndex);
  1540.     }
  1541.   }
  1542.  
  1543.   // Remove them
  1544.   closeShowcaseTabs(targetTabs);
  1545. }
  1546.  
  1547. function closeSelectedTabs() {
  1548.   // Close the selected tabs
  1549.   if (selectedTabs.length > 0) {
  1550.     closeShowcaseTabs(selectedTabs);
  1551.   } else if (currentCursor) {
  1552.     closeShowcaseTab(currentCursor);
  1553.   } else {
  1554.     closeShowcaseTab(showcasePopupTab);
  1555.   }
  1556. }
  1557.  
  1558. function closeSelectedWindow() {
  1559.   // Look for the window that has the tab
  1560.   var found = false;
  1561.   var targetProcessedWindow;
  1562.   for (var c=0; ((c<processedWindows.length) && !found); c++) {
  1563.     if (processedWindows[c].processedTabs.indexOf(showcasePopupTab) > -1) {
  1564.       targetProcessedWindow = processedWindows[c];
  1565.       found = true;
  1566.     }
  1567.   }
  1568.   if (found) {
  1569.     if ((targetProcessedWindow.targetWindow.BrowserTryToCloseWindow) && (typeof(targetProcessedWindow.targetWindow.BrowserTryToCloseWindow) == "function")) {
  1570.       targetProcessedWindow.targetWindow.BrowserTryToCloseWindow();
  1571.     } else {
  1572.       targetProcessedWindow.targetWindow.close();
  1573.     }
  1574.   }
  1575. }
  1576.  
  1577. function getProcessedWindowForProcessedTab(targetProcessedTab) {
  1578.   var foundProcessedTab = false;
  1579.   var returnProcessedWindow = null;
  1580.  
  1581.   for (var c=0; (c<processedWindows.length)&&!foundProcessedTab; c++) {
  1582.     for (var d=0; (d<processedWindows[c].processedTabs.length)&&!foundProcessedTab; d++) {
  1583.       if (targetProcessedTab == processedWindows[c].processedTabs[d]) {
  1584.         foundProcessedTab = true;
  1585.         returnProcessedWindow = processedWindows[c];
  1586.       }
  1587.     }
  1588.   }
  1589.  
  1590.   return returnProcessedWindow;
  1591. }
  1592.  
  1593. function BrowserViewSourceOfDocument(targetProcessedTab, aDocument)
  1594. {
  1595.   var docCharset;
  1596.   var pageCookie;
  1597.   var webNav;
  1598.   var targetWindow = getProcessedWindowForProcessedTab(targetProcessedTab).targetWindow;
  1599.  
  1600.   // Get the document charset
  1601.   docCharset = "charset=" + aDocument.characterSet;
  1602.  
  1603.   // Get the nsIWebNavigation associated with the document
  1604.   try {
  1605.       var win;
  1606.       var ifRequestor;
  1607.  
  1608.       // Get the DOMWindow for the requested document.  If the DOMWindow
  1609.       // cannot be found, then just use the content window...
  1610.       //
  1611.       // XXX:  This is a bit of a hack...
  1612.       win = aDocument.defaultView;
  1613.       if (win == targetWindow) {
  1614.         win = targetWindow.content;
  1615.       }
  1616.       ifRequestor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  1617.  
  1618.       webNav = ifRequestor.getInterface(nsIWebNavigation);
  1619.   } catch(err) {
  1620.       // If nsIWebNavigation cannot be found, just get the one for the whole
  1621.       // window...
  1622.       webNav = targetWindow.getWebNavigation();
  1623.   }
  1624.   //
  1625.   // Get the 'PageDescriptor' for the current document. This allows the
  1626.   // view-source to access the cached copy of the content rather than
  1627.   // refetching it from the network...
  1628.   //
  1629.   try{
  1630.     var PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor);
  1631.  
  1632.     pageCookie = PageLoader.currentDescriptor;
  1633.   } catch(err) {
  1634.     // If no page descriptor is available, just use the view-source URL...
  1635.   }
  1636.  
  1637.   BrowserViewSourceOfURL(webNav.currentURI.spec, docCharset, pageCookie);
  1638. }
  1639.  
  1640. function BrowserViewSourceOfURL(url, charset, pageCookie)
  1641. {
  1642.   // try to open a view-source window while inheriting the charset (if any)
  1643.   
  1644.   openDialog("chrome://global/content/viewSource.xul",
  1645.              "_blank",
  1646.              "scrollbars,resizable,chrome,dialog=no",
  1647.              url, charset, pageCookie);
  1648.   
  1649. }
  1650.  
  1651. function BrowserPageInfo(aDocument)
  1652. {
  1653.   var args = {doc: aDocument, initialTab: null};
  1654.  
  1655.   
  1656.   var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
  1657.   var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
  1658.   var windows = windowManagerInterface.getEnumerator("Browser:page-info");
  1659.  
  1660.   // Check for windows matching the url
  1661.   while (windows.hasMoreElements()) {
  1662.     var currentWindow = windows.getNext();
  1663.     if (currentWindow.document.firstChild.getAttribute("relatedUrl") == aDocument.location) {
  1664.         currentWindow.focus();
  1665.         return;
  1666.     }
  1667.   }
  1668.  
  1669.   // We didn't find a matching window, so open a new one.
  1670.   window.openDialog("chrome://browser/content/pageInfo.xul", "_blank", "chrome,dialog=no", args);
  1671.   
  1672. }
  1673.  
  1674. function getFirstCursor() {
  1675.   return getTabAt(0, 0);
  1676. }
  1677.  
  1678. function getLastCursor() {
  1679.   return getTabAt(mosaicRows, mosaicColumns);
  1680. }
  1681.  
  1682. function getTabAt(targetRow, targetColumn) {
  1683.   // Iterate...
  1684.   var found = false;
  1685.   var targetWindow;
  1686.   var targetProcessedTab = null;
  1687.  
  1688.   for (var c=0; ((c<processedWindows.length) && !found); c++) {
  1689.     targetWindow = processedWindows[c];
  1690.     for (var d=0; ((d<targetWindow.processedTabs.length) && !found); d++) {
  1691.       targetProcessedTab = targetWindow.processedTabs[d];
  1692.       if ((targetProcessedTab.showcaseRow == targetRow) && (targetProcessedTab.showcaseColumn == targetColumn) && !targetProcessedTab.showcaseCanvasBox.hidden) {
  1693.         found = true;
  1694.       }
  1695.     }
  1696.     /*
  1697.     // I'm not entirely sure of the function of this sentence...
  1698.     if (processedWindows[c].processedTabs.indexOf(showcasePopupTab) > -1) {
  1699.       found = true;
  1700.     }
  1701.     */
  1702.   }
  1703.  
  1704.   return targetProcessedTab;
  1705. }
  1706.  
  1707. function keyboardHome(el) {
  1708.   if (inZoomMode) {
  1709.     if (!zoomFitsScreen) {
  1710.       zoomOffsetX = 0;
  1711.       zoomOffsetY = 0;
  1712.       if ((zoomTargetThumbnail.targetTab.contentWindow.scrollX == 0) && 
  1713.           (zoomTargetThumbnail.targetTab.contentWindow.scrollY == 0)) {
  1714.         zoomTargetThumbnail.showcaseCanvas.showcasePainted = false;
  1715.         setTimeout(function foo(a) { paintThumbnail(a); checkScrollCursorsVisibility(); }, 0, zoomTargetThumbnail);
  1716.       }
  1717.     }
  1718.     zoomTargetThumbnail.targetTab.contentWindow.scroll(0, 0);
  1719.     return;
  1720.   }
  1721.  
  1722.   if (!currentCursor) {
  1723.     var result = getFirstCursor();
  1724.     if (result) {
  1725.       result.showcaseCanvasBox.focus();
  1726.     }
  1727.   } else {
  1728.     var result = getFirstCursor();
  1729.  
  1730.     if (result) {
  1731.       if (el.shiftKey) {
  1732.         focusSelectRange = true;
  1733.       } else if (el.ctrlKey) {
  1734.         focusIgnoreSelection = true;
  1735.       }
  1736.  
  1737.       if (currentCursor == result) {
  1738.         processFocusedTab(currentCursor);
  1739.       } else {
  1740.         result.showcaseCanvasBox.focus();
  1741.       }
  1742.     }
  1743.   }
  1744. }
  1745.  
  1746. function keyboardEnd(el) {
  1747.   if (inZoomMode) {
  1748.     if (!zoomFitsScreen) {
  1749.       zoomOffsetX = zoomTotalWidth - zoomCurrentWidth;
  1750.       zoomOffsetY = zoomTotalHeight - zoomCurrentHeight;
  1751.       if ((zoomTargetThumbnail.targetTab.contentWindow.scrollX >= zoomTargetThumbnail.targetTab.contentWindow.scrollMaxX) && 
  1752.           (zoomTargetThumbnail.targetTab.contentWindow.scrollY >= zoomTargetThumbnail.targetTab.contentWindow.scrollMaxY)) {
  1753.         zoomTargetThumbnail.showcaseCanvas.showcasePainted = false;
  1754.         setTimeout(function foo(a) { paintThumbnail(a); checkScrollCursorsVisibility(); }, 0, zoomTargetThumbnail);
  1755.       }
  1756.     }
  1757.     zoomTargetThumbnail.targetTab.contentWindow.scrollBy(zoomTargetThumbnail.targetTab.contentWindow.scrollMaxX - zoomTargetThumbnail.targetTab.contentWindow.scrollX, zoomTargetThumbnail.targetTab.contentWindow.scrollMaxY - zoomTargetThumbnail.targetTab.contentWindow.scrollY);
  1758.     return;
  1759.   }
  1760.  
  1761.   if (!currentCursor) {
  1762.     var result = getLastCursor();
  1763.     if (result) {
  1764.       result.showcaseCanvasBox.focus();
  1765.     }
  1766.   } else {
  1767.     var result = getLastCursor();
  1768.  
  1769.     if (result) {
  1770.       if (el.shiftKey) {
  1771.         focusSelectRange = true;
  1772.       } else if (el.ctrlKey) {
  1773.         focusIgnoreSelection = true;
  1774.       }
  1775.  
  1776.       if (currentCursor == result) {
  1777.         processFocusedTab(currentCursor);
  1778.       } else {
  1779.         result.showcaseCanvasBox.focus();
  1780.       }
  1781.     }
  1782.   }
  1783. }
  1784. function keyboardLeft(el) {
  1785.   if (inZoomMode) {
  1786.     zoomPanLeft(zoomScrollIncrement);
  1787.     return;
  1788.   }
  1789.  
  1790.   if (!currentCursor) {
  1791.     var result = getLastCursor();
  1792.     if (result) {
  1793.       result.showcaseCanvasBox.focus();
  1794.     }
  1795.   } else {
  1796.     var targetRow = currentCursor.showcaseRow;
  1797.     var targetColumn = currentCursor.showcaseColumn;
  1798.  
  1799.     if (targetColumn > 0) {
  1800.       targetColumn--;
  1801.     }
  1802.     var result = getTabAt(targetRow, targetColumn);
  1803.  
  1804.     if (result) {
  1805.       if (el.shiftKey) {
  1806.         focusSelectRange = true;
  1807.       } else if (el.ctrlKey) {
  1808.         focusIgnoreSelection = true;
  1809.       }
  1810.  
  1811.       if (currentCursor == result) {
  1812.         processFocusedTab(currentCursor);
  1813.       } else {
  1814.         result.showcaseCanvasBox.focus();
  1815.       }
  1816.     } else {
  1817.       var result = getLastCursor();
  1818.       if (result) {
  1819.         result.showcaseCanvasBox.focus();
  1820.       }
  1821.     }
  1822.   }
  1823. }
  1824.  
  1825. function keyboardRight(el) {
  1826.   if (inZoomMode) {
  1827.     zoomPanRight(zoomScrollIncrement);
  1828.     zoomTargetThumbnail.targetTab.contentWindow.scrollBy(zoomScrollIncrement, 0);
  1829.     return;
  1830.   }
  1831.  
  1832.   if (!currentCursor) {
  1833.     var result = getFirstCursor();
  1834.     if (result) {
  1835.       result.showcaseCanvasBox.focus();
  1836.     }
  1837.   } else {
  1838.     var targetRow = currentCursor.showcaseRow;
  1839.     var targetColumn = currentCursor.showcaseColumn;
  1840.  
  1841.     if (targetColumn < mosaicColumns - 1) {
  1842.       targetColumn++;
  1843.     }
  1844.     var result = getTabAt(targetRow, targetColumn);
  1845.  
  1846.     if (result) {
  1847.       if (el.shiftKey) {
  1848.         focusSelectRange = true;
  1849.       } else if (el.ctrlKey) {
  1850.         focusIgnoreSelection = true;
  1851.       }
  1852.  
  1853.       if (currentCursor == result) {
  1854.         processFocusedTab(currentCursor);
  1855.       } else {
  1856.         result.showcaseCanvasBox.focus();
  1857.       }
  1858.     } else {
  1859.       var result = getFirstCursor();
  1860.       if (result) {
  1861.         result.showcaseCanvasBox.focus();
  1862.       }
  1863.     }
  1864.   }
  1865. }
  1866.  
  1867. function keyboardUp(el) {
  1868.   if (inZoomMode) {
  1869.     zoomPanUp(zoomScrollIncrement);
  1870.     return;
  1871.   }
  1872.  
  1873.   if (!currentCursor) {
  1874.     var result = getLastCursor();
  1875.     if (result) {
  1876.       currentCursor = result;
  1877.       currentCursor.showcaseCanvasBox.focus();
  1878.     }
  1879.   } else {
  1880.     var targetRow = currentCursor.showcaseRow;
  1881.     var targetColumn = currentCursor.showcaseColumn;
  1882.  
  1883.     if (targetRow > 0) {
  1884.       targetRow--;
  1885.     }
  1886.     var result = getTabAt(targetRow, targetColumn);
  1887.  
  1888.     if (result) {
  1889.       if (el.shiftKey) {
  1890.         focusSelectRange = true;
  1891.       } else if (el.ctrlKey) {
  1892.         focusIgnoreSelection = true;
  1893.       }
  1894.  
  1895.       if (currentCursor == result) {
  1896.         processFocusedTab(currentCursor);
  1897.       } else {
  1898.         result.showcaseCanvasBox.focus();
  1899.       }
  1900.     } else {
  1901.       var result = getLastCursor();
  1902.       if (result) {
  1903.         currentCursor = result;
  1904.         currentCursor.showcaseCanvasBox.focus();
  1905.       }
  1906.     }
  1907.   }
  1908. }
  1909.  
  1910. function keyboardDown(el) {
  1911.   if (inZoomMode) {
  1912.     zoomPanDown(zoomScrollIncrement);
  1913.     return;
  1914.   }
  1915.  
  1916.   if (!currentCursor) {
  1917.     var result = getFirstCursor();
  1918.     if (result) {
  1919.       result.showcaseCanvasBox.focus();
  1920.     }
  1921.   } else {
  1922.     var targetRow = currentCursor.showcaseRow;
  1923.     var targetColumn = currentCursor.showcaseColumn;
  1924.  
  1925.     if (targetRow < mosaicRows - 1) {
  1926.       targetRow++;
  1927.     }
  1928.     var result = getTabAt(targetRow, targetColumn);
  1929.  
  1930.     if (result && (result.showcaseColumn == targetColumn)) {
  1931.       if (el.shiftKey) {
  1932.         focusSelectRange = true;
  1933.       } else if (el.ctrlKey) {
  1934.         focusIgnoreSelection = true;
  1935.       }
  1936.  
  1937.       if (currentCursor == result) {
  1938.         processFocusedTab(currentCursor);
  1939.       } else {
  1940.         result.showcaseCanvasBox.focus();
  1941.       }
  1942.     } else if (!result) {
  1943.       var result = getFirstCursor();
  1944.       if (result) {
  1945.         result.showcaseCanvasBox.focus();
  1946.       }
  1947.     }
  1948.   }
  1949. }
  1950.  
  1951. function keyboardEnter() {
  1952.   if (!currentCursor)
  1953.     return;
  1954.   openTab(currentCursor);
  1955. }
  1956.  
  1957. function windowKeyDown(ev) {
  1958.   if (ev.keyCode == VK_SPACE) {
  1959.     if (!currentCursor)
  1960.       return;
  1961.     
  1962.     if (ev.ctrlKey) {
  1963.       toggleSelection(currentCursor);
  1964.     } else {
  1965.       enterZoomMode(currentCursor);
  1966.     }
  1967.   }
  1968. }
  1969.  
  1970. function windowKeyUp(ev) {
  1971.   if (ev.keyCode == VK_SPACE) {
  1972.     if (!currentCursor)
  1973.       return;
  1974.  
  1975.     if (!ev.ctrlKey) {
  1976.       leaveZoomMode();
  1977.     }
  1978.   } else if ((ev.keyCode == VK_PRIOR) && (inZoomMode)) {
  1979.     if (zoomFitsScreen) {
  1980.       zoomPanUp(zoomTargetThumbnail.targetTab.contentWindow.innerHeight);
  1981.     } else {
  1982.       zoomPanUp(zoomTotalHeight);
  1983.     }
  1984.   } else if ((ev.keyCode == VK_NEXT) && (inZoomMode)) {
  1985.     if (zoomFitsScreen) {
  1986.       zoomPanDown(zoomTargetThumbnail.targetTab.contentWindow.innerHeight);
  1987.     } else {
  1988.       zoomPanDown(zoomTotalHeight);
  1989.     }
  1990.   }
  1991. }
  1992.  
  1993. function keyboardDelete() {
  1994.   if ((!currentCursor) && (selectedTabs.length == 0))
  1995.     return;
  1996.  
  1997.   if (inZoomMode)
  1998.     leaveZoomMode();
  1999.   
  2000.   closeSelectedTabs();
  2001. }
  2002.  
  2003. function toggleFullScreen() {
  2004.   if (topWindow == window) {
  2005.     window.fullScreen = !window.fullScreen;
  2006.   } else {
  2007.     topWindow.fullScreen = !topWindow.fullScreen;
  2008.   }
  2009. }
  2010.  
  2011. function setCanvasSize(targetCanvas, width, height) {
  2012.   targetCanvas.style.width = width+"px";
  2013.   targetCanvas.style.height = height+"px";
  2014.   targetCanvas.style.maxWidth = targetCanvas.style.width;
  2015.   targetCanvas.style.minWidth = targetCanvas.style.width;
  2016.   targetCanvas.style.maxHeight = targetCanvas.style.height;
  2017.   targetCanvas.style.minHeight = targetCanvas.style.height;
  2018. }
  2019.  
  2020. function setSize(targetElement,width,height) {
  2021.   targetElement.setAttribute("width", width);
  2022.   targetElement.setAttribute("height", height);
  2023.  
  2024.   targetElement.style.width = width+"px";
  2025.   targetElement.style.height = height+"px";
  2026. //  targetElement.style.minWidth = targetElement.style.width;
  2027. //  targetElement.style.minHeight = targetElement.style.height;
  2028.   targetElement.style.maxWidth = targetElement.style.width;
  2029.   targetElement.style.maxHeight = targetElement.style.height;
  2030. }
  2031.  
  2032. function createContent() {
  2033.   try {
  2034.     var windows = getTargetWindows();
  2035.     var shouldRefresh = false;
  2036.  
  2037.     for (var i = 0; i < windows.length; i++) {
  2038.       try {
  2039.         linkWindow(windows[i]);
  2040.         shouldRefresh = true;
  2041.       } catch (e) {
  2042.         // We failed, check window later
  2043.         setTimeout(checkWindow, 100, windows[i], 15);
  2044.       }
  2045.     }
  2046.  
  2047.     if (windows.length > 0) {
  2048.       document.getElementById("emptyMessage").setAttribute("hidden", true);
  2049.     } else {
  2050.       document.getElementById("emptyMessage").setAttribute("hidden", false);
  2051.       shouldRefresh = true;
  2052.     }
  2053.  
  2054.     for (var j=0; j<processedWindows.length; j++) {
  2055.       updateBorders(processedWindows[j]);
  2056.     }
  2057.  
  2058.     if (shouldRefresh) {
  2059.       updateTitle();
  2060.       //setTimeout(refreshContent, 0);
  2061.       refreshContent();
  2062.     }
  2063.   } catch (e) {
  2064.       alert("createContent - " + e);
  2065.   }
  2066. }
  2067.  
  2068. function newWindowLoaded(event) {
  2069.   event.currentTarget.removeEventListener("load", newWindowLoaded, false);
  2070.   setTimeout(createContent, 0);
  2071. }
  2072.  
  2073. function createThumbnail(targetTabHeader, targetProcessedTab, tabbrowser, tabwindow) {
  2074.   var canvasBox;
  2075.  
  2076.   if (thumbnailShowLabels) {
  2077.     if (thumbnailLabelStyle == 0) {
  2078.       // in a box
  2079.       canvasBox = document.getElementById('thumbnail-box-template').firstChild.cloneNode(true);
  2080.     } else if (thumbnailLabelStyle == 1) {
  2081.       canvasBox = document.getElementById('thumbnail-plain-template').firstChild.cloneNode(true);
  2082.     } else if (thumbnailLabelStyle == 2) {
  2083.       canvasBox = document.getElementById('thumbnail-plainclose-template').firstChild.cloneNode(true);
  2084.     }
  2085.   } else {
  2086.     canvasBox = document.getElementById('thumbnail-nolabel-template').firstChild.cloneNode(true);
  2087.   }
  2088.   
  2089.   var canvas = canvasBox.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "canvas").item(0);
  2090.   var subCanvasBox = canvas.parentNode;
  2091.  
  2092.   if (thumbnailShowLabels) {
  2093.     canvasBox.showcaseLabel = canvasBox.getElementsByTagName("label").item(0);
  2094.     canvasBox.showcaseImageLabel = canvasBox.getElementsByTagName("image").item(0);
  2095.     if (thumbnailLabelStyle == 0) {
  2096.       canvasBox.showcaseCloseButton = canvasBox.getElementsByTagName("toolbarbutton").item(0);
  2097.     } else if (thumbnailLabelStyle == 2) {
  2098.       canvasBox.showcaseCloseButton = canvasBox.getElementsByTagName("image").item(1);
  2099.     }
  2100.   }
  2101.  
  2102.   if (canvasBox.showcaseCloseButton) {
  2103.     canvasBox.showcaseCloseButton.targetProcessedTab = targetProcessedTab;
  2104.     canvasBox.showcaseCloseButton.addEventListener("click", mouseClickClose, true);
  2105.   }
  2106.   
  2107.   if (isFirefox35) {
  2108.     canvasBox.setAttribute("draggable", true);
  2109.     canvasBox.setAttribute("ondragstart", "newDragDropHandler.onDragStart(event);");
  2110.     if (((dragDropExclude & 1) > 0) && (canvasBox.showcaseCloseButton)) {
  2111.       canvasBox.showcaseCloseButton.setAttribute("draggable", false);
  2112.     }
  2113.     if ((dragDropExclude & 2) > 0) {
  2114.       subCanvasBox.setAttribute("draggable", false);
  2115.     }
  2116.     
  2117.   } else {
  2118.     canvasBox.setAttribute("ondraggesture", "nsDragAndDrop.startDrag(event,thumbnailObserver)");
  2119.     canvasBox.setAttribute("ondragdrop", "return thumbnailObserver.checkOwnDrop(event, nsDragAndDrop.mDragSession);");
  2120.     
  2121.     if (((dragDropExclude & 1) > 0) && (canvasBox.showcaseCloseButton)) {
  2122.       canvasBox.showcaseCloseButton.setAttribute("ondraggesture", "if (selectedTabs.length < 2) event.stopPropagation();");
  2123.     }
  2124.     if ((dragDropExclude & 2) > 0) {
  2125.       subCanvasBox.setAttribute("ondraggesture", "if (selectedTabs.length < 2) event.stopPropagation();");
  2126.     }
  2127.   }
  2128.  
  2129.   canvasBox.addEventListener("focus", thumbnailFocus, false);
  2130.   canvasBox.addEventListener("blur", thumbnailBlur, false);
  2131.  
  2132.   if (thumbnailActiveAnimation || selectWhenMouseOver || thumbnailBackButton || thumbnailForwardButton || thumbnailStopButton || thumbnailReloadButton || thumbnailHistoryButton) {
  2133.     canvasBox.addEventListener("mouseover", mouseOverCanvas, false);
  2134.     canvasBox.addEventListener("mouseout", mouseOutCanvas, false);
  2135.   }
  2136.  
  2137.   canvasBox.addEventListener("mousedown", mouseDownCanvas, (topWindow != window));
  2138.   canvasBox.addEventListener("mouseup", mouseUpCanvas, (topWindow != window));
  2139.   if (doubleClickOpen) {
  2140.     canvasBox.addEventListener("dblclick", mouseDoubleClickCanvas, (topWindow != window));
  2141.   }
  2142.  
  2143.   targetProcessedTab.showcaseCanvas = canvas;
  2144.   targetProcessedTab.showcaseCanvas.showcaseCanvasBox = canvasBox;
  2145.   targetProcessedTab.showcaseCanvasBox = canvasBox;
  2146.   targetProcessedTab.showcaseCanvasBox.showcaseCanvas = canvas;
  2147.   targetProcessedTab.showcaseCanvasBox.showcaseTab = targetProcessedTab;
  2148.   targetProcessedTab.tabHeader = targetTabHeader;
  2149.  
  2150.   targetProcessedTab.showcaseCanvasSubBox = subCanvasBox;
  2151.  
  2152.   targetProcessedTab.showcaseProgressListener = new TabProgressListener(targetProcessedTab);
  2153.  
  2154.   if (targetProcessedTab.targetTab.contentDocument) {
  2155.     if (targetProcessedTab.targetTab.contentDocument.URL) {
  2156.       if ((detectIETab) && (targetProcessedTab.targetTab.contentDocument.URL.substr(0, IETAB_URL.length) == IETAB_URL)) {
  2157.         targetProcessedTab.showcaseIETab = true;
  2158.         updateIEState(targetProcessedTab);
  2159.       } else if ((detectBlank) && ((targetProcessedTab.targetTab.contentDocument.URL == "") || (targetProcessedTab.targetTab.contentDocument.URL == "about:blank"))) {
  2160.         targetProcessedTab.showcaseBlank = true;
  2161.         updateBlankState(targetProcessedTab);
  2162.       }
  2163.     }
  2164.     checkEmbedding(targetProcessedTab, false);
  2165.     checkImage(targetProcessedTab);
  2166.   }
  2167.  
  2168.   targetProcessedTab.showcaseTabEventListener = new TabEventListener(targetProcessedTab, tabwindow, window);
  2169.   targetProcessedTab.targetTab.addEventListener("resize", targetProcessedTab.showcaseTabEventListener, false);
  2170.   targetProcessedTab.targetTab.addEventListener("load", targetProcessedTab.showcaseTabEventListener, true);
  2171.   if (thumbnailShowLabels) {
  2172.     targetProcessedTab.tabHeader.addEventListener("DOMAttrModified", targetProcessedTab.showcaseTabEventListener, false);
  2173.     if (targetTabHeader.hasAttribute("busy")) {
  2174.       targetProcessedTab.showcaseProgressListener.progressListener.isLoading = true;
  2175.       updateLoadingState(targetProcessedTab);
  2176.     }
  2177.     canvasBox.showcaseLabel.setAttribute("value", targetTabHeader.label);
  2178.     canvasBox.showcaseLabel.setAttribute("tooltiptext", targetTabHeader.label);
  2179.     canvasBox.showcaseImageLabel.setAttribute("tooltiptext", targetTabHeader.label);
  2180.     canvasBox.showcaseImageLabel.setAttribute("src", targetTabHeader.getAttribute("image"));
  2181.     canvasBox.showcaseLabel.setAttribute("crop", targetTabHeader.getAttribute("crop"));
  2182.   }
  2183.  
  2184.   if (updateThumbnailWhenScroll) {
  2185.     targetProcessedTab.targetTab.addEventListener("scroll", targetProcessedTab.showcaseTabEventListener, true);
  2186.   }
  2187.  
  2188.   targetProcessedTab.targetTabWindow = tabwindow;
  2189.  
  2190.   return canvasBox;
  2191. }
  2192.  
  2193. function showcaseSelectedWindow() {
  2194.   if (closingShowcase) {
  2195.     return;
  2196.   }
  2197.   
  2198.   // Set new target
  2199.   if (selectedTabs.length > 0) {
  2200.     localTargetWindow = selectedTabs[0].targetTabWindow.targetWindow;
  2201.   } else {
  2202.     localTargetWindow = window.showcasePopupTab.targetTabWindow.targetWindow;
  2203.   }
  2204.  
  2205.   // Unlink showcase
  2206.   unlinkShowcase(CACHEMODE_UPDATE);
  2207.  
  2208.   // Reset showcase sidebar title
  2209.   showcaseOriginalTitle = null;
  2210.  
  2211.   // Set new mode
  2212.   globalMode = false;
  2213.  
  2214.   // Startup...
  2215.   contentStartup(false);
  2216. }
  2217.  
  2218. function refreshScreen() {
  2219.   if (closingShowcase) {
  2220.     return;
  2221.   }
  2222.  
  2223.   // Unlink showcase
  2224.   unlinkShowcase(CACHEMODE_CLEAR);
  2225.  
  2226.   // Reset window color
  2227.   windowCurrentColor = 1;
  2228.  
  2229.   // Reset status bar
  2230.   if (scrollActivated) {
  2231.     showcaseContentVertical.removeAttribute("scrolling");
  2232.     scrollActivated = false;
  2233.   }
  2234.  
  2235.   // Reset margins
  2236.   thumbnailBorderWidth = -1;
  2237.   thumbnailBorderHeight = -1;
  2238.  
  2239.   // Reload contextual settings
  2240.   loadedContextualSettings = false;
  2241.  
  2242.   // Reload settings
  2243.   loadSettings();
  2244.  
  2245.   initShowcase();
  2246.  
  2247.   // Startup...
  2248.   contentStartup(false);
  2249. }
  2250.  
  2251. function refreshContent() {
  2252.   if (searchActive) {
  2253.     updateFind();
  2254.   } else if (showOnlyCurrent) {
  2255.     updateShowOnlyCurrent();
  2256.   }
  2257.  
  2258.   // Extend showcase box
  2259.   var innerBox = document.getElementById("showcase-content-horizontal");
  2260.  
  2261.   // Mosaic code
  2262.   if ((innerBox.boxObject.width > 100) && (innerBox.boxObject.height > 100)) {
  2263.     mosaicWidth = innerBox.boxObject.width;
  2264.     mosaicHeight = innerBox.boxObject.height;
  2265.   } else if ((showcaseBox.boxObject.width > 100) && (showcaseBox.boxObject.height > 100)){
  2266.     mosaicWidth = showcaseBox.boxObject.width;
  2267.     mosaicHeight = showcaseBox.boxObject.height;
  2268.   } else {
  2269.     if (innerBox.boxObject.width > 100) {
  2270.       mosaicWidth = innerBox.boxObject.width;
  2271.     } else {
  2272.       mosaicWidth = 100;
  2273.     }
  2274.     if (innerBox.boxObject.height > 100) {
  2275.       mosaicHeight = innerBox.boxObject.height;
  2276.     } else {
  2277.       mosaicHeight = 100;
  2278.     }
  2279.   }
  2280.   if (!inZoomMode) {
  2281.     var mosaicSizeResult = mosaicCalculateBestGrid(mosaicWidth, mosaicHeight);
  2282.     mosaicRows = mosaicSizeResult[0];
  2283.     mosaicColumns = mosaicSizeResult[1];
  2284.     thumbWidth =  Math.ceil(mosaicWidth / mosaicColumns);
  2285.     thumbHeight = Math.ceil(mosaicHeight / mosaicRows);
  2286.     
  2287.     if (scrollType == SCROLL_VERTICAL) {
  2288.       var estimatedThumbWidth = (thumbHeight - thumbnailBorderHeight) * mosaicSizeResult[2] / mosaicSizeResult[3];
  2289.       if (estimatedThumbWidth > (thumbWidth - thumbnailBorderWidth)) {
  2290.         estimatedThumbWidth = thumbWidth - thumbnailBorderWidth;
  2291.       }
  2292.  
  2293.       if ((estimatedThumbWidth < thumbnailPreferredMinimumSize) || alwaysShowScrollbar) {
  2294.         // Adjust width
  2295.         var newMosaicWidth = mosaicWidth;
  2296.         if (newMosaicWidth > verticalScrollbarWidth) {
  2297.           newMosaicWidth -= verticalScrollbarWidth;
  2298.         }
  2299.  
  2300.         var newMosaicColumns = Math.floor(newMosaicWidth / thumbnailPreferredMinimumSize);
  2301.  
  2302.         if (newMosaicColumns > mosaicSizeResult[4]) {
  2303.           newMosaicColumns = mosaicSizeResult[4];
  2304.         }
  2305.  
  2306.         if (newMosaicColumns <= 0) {
  2307.           newMosaicColumns = 1;
  2308.         }
  2309.  
  2310.         var newMosaicRows = Math.floor(mosaicSizeResult[4] / newMosaicColumns);
  2311.         if ((mosaicSizeResult[4] % newMosaicColumns) > 0) {
  2312.           newMosaicRows++;
  2313.         }
  2314.         newThumbWidth = Math.ceil(newMosaicWidth / newMosaicColumns);
  2315.         newThumbHeight = Math.ceil((newThumbWidth - thumbnailBorderWidth) * mosaicSizeResult[3] / mosaicSizeResult[2]) + thumbnailBorderHeight;
  2316. /*
  2317.         var newMosaicHeight = thumbHeight * mosaicRows;
  2318.         if (newMosaicHeight > mosaicHeight) {
  2319.           mosaicHeight = newMosaicHeight;
  2320.         } else {
  2321.           thumbHeight = Math.ceil(mosaicHeight / mosaicRows);
  2322.         }
  2323. */
  2324.         var newMosaicHeight = mosaicHeight;
  2325.         if (newMosaicRows > 0)
  2326.           newMosaicHeight = newThumbHeight * newMosaicRows;
  2327.  
  2328.         if (((newThumbWidth - thumbnailBorderWidth) > estimatedThumbWidth) || alwaysShowScrollbar) {
  2329.           thumbWidth = newThumbWidth;
  2330.           thumbHeight = newThumbHeight;
  2331.           mosaicRows = newMosaicRows;
  2332.           mosaicColumns = newMosaicColumns;
  2333.           mosaicWidth = newMosaicWidth;
  2334.           mosaicHeight = newMosaicHeight;
  2335.  
  2336.           // Activate scrolling
  2337.           if (!scrollActivated) {
  2338.             scrollActivated = true;
  2339.             showcaseContentVertical.setAttribute("scrolling", "vertical");
  2340.           }
  2341.         } else if (scrollActivated) {
  2342.           scrollActivated = false;
  2343.           showcaseContentVertical.removeAttribute("scrolling");
  2344.         }
  2345.       } else if (scrollActivated) {
  2346.         scrollActivated = false;
  2347.         showcaseContentVertical.removeAttribute("scrolling");
  2348.       }
  2349.     } else if (scrollType == SCROLL_HORIZONTAL) {
  2350.       var estimatedThumbHeight = (thumbWidth - thumbnailBorderWidth) * mosaicSizeResult[3] / mosaicSizeResult[2];
  2351.       if (estimatedThumbHeight > (thumbHeight - thumbnailBorderHeight)) {
  2352.         estimatedThumbHeight = thumbHeight - thumbnailBorderHeight;
  2353.       }
  2354.  
  2355.       if ((estimatedThumbHeight < thumbnailPreferredMinimumSize) || alwaysShowScrollbar) {
  2356.         // Activate scrolling
  2357.         if (!scrollActivated) {
  2358.           scrollActivated = true;
  2359.           showcaseContentVertical.setAttribute("scrolling", "horizontal");
  2360.         }
  2361.  
  2362.         // Adjust width
  2363.         var newMosaicHeight = mosaicHeight;
  2364.         if (newMosaicHeight > horizontalScrollbarHeight) {
  2365.           newMosaicHeight -= horizontalScrollbarHeight;
  2366.         }
  2367.  
  2368.         var newMosaicRows = Math.floor(newMosaicHeight / thumbnailPreferredMinimumSize);
  2369.  
  2370.         if (newMosaicRows > mosaicSizeResult[4]) {
  2371.           newMosaicRows = mosaicSizeResult[4];
  2372.         }
  2373.  
  2374.         if (newMosaicRows <= 0) {
  2375.           newMosaicRows = 1;
  2376.         }
  2377.  
  2378.         var newMosaicColumns = Math.floor(mosaicSizeResult[4] / newMosaicRows);
  2379.         if ((mosaicSizeResult[4] % newMosaicRows) > 0) {
  2380.           newMosaicColumns++;
  2381.         }
  2382.         var newThumbHeight = Math.ceil(newMosaicHeight / newMosaicRows);
  2383.         var newThumbWidth = Math.ceil((newThumbHeight - thumbnailBorderHeight) * mosaicSizeResult[2] / mosaicSizeResult[3]) + thumbnailBorderWidth;
  2384. /*
  2385.         var newMosaicWidth = thumbWidth * mosaicColumns;
  2386.         if (newMosaicWidth > mosaicWidth) {
  2387.           mosaicWidth = newMosaicWidth;
  2388.         } else {
  2389.           thumbWidth = Math.ceil(mosaicWidth / mosaicColumns);
  2390.         }
  2391. */
  2392.         var newMosaicWidth = mosaicWidth;
  2393.         if (newMosaicColumns > 0)
  2394.           newMosaicWidth = newThumbWidth * newMosaicColumns;
  2395.  
  2396.         if (((newThumbHeight - thumbnailBorderHeight) > estimatedThumbHeight) || alwaysShowScrollbar) {
  2397.           thumbWidth = newThumbWidth;
  2398.           thumbHeight = newThumbHeight;
  2399.           mosaicRows = newMosaicRows;
  2400.           mosaicColumns = newMosaicColumns;
  2401.           mosaicWidth = newMosaicWidth;
  2402.           mosaicHeight = newMosaicHeight;
  2403.  
  2404.           // Activate scrolling
  2405.           if (!scrollActivated) {
  2406.             scrollActivated = true;
  2407.             showcaseContentVertical.setAttribute("scrolling", "horizontal");
  2408.           }
  2409.         } else if (scrollActivated) {
  2410.           scrollActivated = false;
  2411.           showcaseContentVertical.removeAttribute("scrolling");
  2412.         }
  2413.       } else if (scrollActivated) {
  2414.         scrollActivated = false;
  2415.         showcaseContentVertical.removeAttribute("scrolling");
  2416.       }
  2417.     }
  2418.   } else {
  2419.     if (scrollActivated) {
  2420.       showcaseContentVertical.removeAttribute("scrolling");
  2421.       scrollActivated = false;
  2422.     }
  2423.  
  2424.     // In zoom mode, set a bit of margin to avoid errors...
  2425.     thumbWidth =  mosaicWidth;
  2426.     thumbHeight = mosaicHeight;
  2427.   }
  2428.  
  2429.   setSize(showcaseBox, mosaicWidth, mosaicHeight);
  2430.  
  2431.   updateThumbnails(thumbWidth, thumbHeight, thumbnailIdleSizeFactor / 100, thumbnailActiveSizeFactor / 100);
  2432.   mosaicRefresh();
  2433.  
  2434.   if (currentIconsThumbnail) {
  2435.     if (inZoomMode || (currentIconsThumbnail.hidden)) {
  2436.       hideThumbnailIcons();
  2437.     } else {
  2438.       showThumbnailIcons();
  2439.     }
  2440.   }
  2441. }
  2442.  
  2443. function zoomIn() {
  2444.   if (inZoomMode) return;
  2445.   
  2446.   if ((scrollType == SCROLL_VERTICAL) && (mosaicColumns > 1)) {
  2447.     if (!scrollActivated) mosaicWidth -= verticalScrollbarWidth;
  2448.     thumbnailPreferredMinimumSize = Math.floor(mosaicWidth / (mosaicColumns - 1));
  2449.     refreshContent();
  2450.   } else if ((scrollType == SCROLL_HORIZONTAL) && (mosaicRows > 1)) {
  2451.     if (!scrollActivated) mosaicHeight -= horizontalScrollbarHeight;
  2452.     thumbnailPreferredMinimumSize = Math.floor(mosaicHeight / (mosaicRows - 1));
  2453.     refreshContent();
  2454.   }
  2455. }
  2456.  
  2457. function zoomOut() {
  2458.   if (inZoomMode) return;
  2459.   
  2460.   if ((scrollType == SCROLL_VERTICAL) && (thumbnailPreferredMinimumSize > 10)) {
  2461.     if (!scrollActivated) mosaicWidth -= verticalScrollbarWidth;
  2462.     thumbnailPreferredMinimumSize = Math.floor(mosaicWidth / (mosaicColumns + 1));
  2463.     if (thumbnailPreferredMinimumSize < 10) thumbnailPreferredMinimumSize = 10;
  2464.     refreshContent();
  2465.   } else if ((scrollType == SCROLL_HORIZONTAL) && (thumbnailPreferredMinimumSize > 10)) {
  2466.     if (!scrollActivated) mosaicHeight -= horizontalScrollbarHeight;
  2467.     thumbnailPreferredMinimumSize = Math.floor(mosaicHeight / (mosaicRows + 1));
  2468.     if (thumbnailPreferredMinimumSize < 10) thumbnailPreferredMinimumSize = 10;
  2469.     refreshContent();
  2470.   }
  2471. }
  2472.  
  2473. function sizeChanged(el) {
  2474.   refreshContent();
  2475. }
  2476.  
  2477. function handleMouseWheel(el) {
  2478.   if (el.ctrlKey || el.shiftKey || el.altKey || el.metaKey) {
  2479.     var actualNode = el.originalTarget;
  2480.     while (actualNode != showcaseContentVertical && !actualNode.showcaseTab && actualNode.parentNode) {
  2481.       actualNode = actualNode.parentNode;
  2482.     }
  2483.     if (actualNode.showcaseTab) {
  2484.       if (el.detail == -32768) {
  2485.         actualNode.showcaseTab.targetTab.contentDocument.defaultView.scrollBy(-zoomScrollIncrement, 0);
  2486.       } else if (el.detail == 32768) {
  2487.         actualNode.showcaseTab.targetTab.contentDocument.defaultView.scrollBy(zoomScrollIncrement, 0);
  2488.       } else {
  2489.         actualNode.showcaseTab.targetTab.contentDocument.defaultView.scrollByLines(el.detail*3);
  2490.       }
  2491.     }
  2492.   } else if (scrollActivated) {
  2493.     // Control regular scroll
  2494.     var targetThumbnail;
  2495.     var scrollX = {};
  2496.     var scrollY = {};
  2497.     scrollBoxObject.getPosition(scrollX,scrollY);
  2498.     var linesToScroll = el.detail / 3;
  2499.     if (scrollType == SCROLL_VERTICAL) {
  2500.       var targetRow;
  2501.       var nextTargetRow;
  2502.       if (linesToScroll > 0) {
  2503.         targetRow = Math.floor((scrollY.value + scrollBoxObject.height) * mosaicRows / mosaicHeight);
  2504.         if (targetRow > mosaicRows) targetRow = mosaicRows;
  2505.         nextTargetRow = targetRow + 1;
  2506.         if (nextTargetRow > mosaicRows) nextTargetRow = -1;
  2507.       } else {
  2508.         targetRow = Math.floor(scrollY.value * mosaicRows / mosaicHeight);
  2509.         if (targetRow < 0) targetRow = 0;
  2510.         nextTargetRow = targetRow - 1;
  2511.         if (nextTargetRow < 0) nextTargetRow = -1;
  2512.       }
  2513.       targetThumbnail = getTabAt(targetRow, 0);
  2514.       if (isThumbnailVisible(targetThumbnail.showcaseCanvasBox) && (nextTargetRow != -1)) {
  2515.         targetThumbnail = getTabAt(nextTargetRow, 0);
  2516.       }
  2517.     } else if (scrollType == SCROLL_HORIZONTAL) {
  2518.       var targetColumn;
  2519.       var nextTargetColumn;
  2520.       if (linesToScroll > 0) {
  2521.         targetColumn = Math.floor((scrollX.value + scrollBoxObject.width) * mosaicColumns / mosaicWidth);
  2522.         if (targetColumn > mosaicColumns) targetColumn = mosaicColumns;
  2523.         nextTargetRow = targetRow + 1;
  2524.         if (nextTargetColumn > mosaicColumns) nextTargetColumn = -1;
  2525.       } else {
  2526.         targetColumn = Math.floor(scrollX.value * mosaicColumns / mosaicWidth);
  2527.         if (targetColumn < 0) targetColumn = 0;
  2528.         nextTargetColumn = targetColumn - 1;
  2529.         if (nextTargetColumn < 0) nextTargetColumn = -1;
  2530.       }
  2531.       targetThumbnail = getTabAt(0, targetColumn);
  2532.       if (isThumbnailVisible(targetThumbnail.showcaseCanvasBox) && (nextTargetColumn != -1)) {
  2533.         targetThumbnail = getTabAt(0, nextTargetColumn);
  2534.       }
  2535.     }
  2536.     ensureThumbnailIsVisible(targetThumbnail.showcaseCanvasBox);
  2537.   }
  2538.   el.preventDefault();
  2539.   el.stopPropagation();
  2540. }
  2541.  
  2542. function hiddenTabPopup(ep) {
  2543.   var tabMenu = document.getElementById("tabMenu");
  2544.  
  2545.   for (var i = 0; i < tabMenu.childNodes.length; i++) {
  2546.     tabMenu.childNodes[i].setAttribute("hidden", true);
  2547.   }
  2548. }
  2549.  
  2550. function showingTabPopup(ep) {
  2551.   if (rightClickAction != 4) {
  2552.     ep.preventDefault();
  2553.     return;
  2554.   }
  2555.  
  2556.   var lastSeparator = null;
  2557.   
  2558.   if (selectedTabs.length < 1) {
  2559.     if (document.popupNode.showcaseCanvasBox) {
  2560.       showcasePopupTab = document.popupNode.showcaseCanvasBox.showcaseTab;
  2561.     } else {
  2562.       showcasePopupTab = document.popupNode.showcaseTab;
  2563.     }
  2564.   } else {
  2565.     showcasePopupTab = selectedTabs[0];
  2566.   }
  2567.  
  2568.   if (!loadedContextualSettings) {
  2569.     loadContextualSettings();
  2570.   }
  2571.  
  2572.   // "Open" action
  2573.   var showMainSeparator = false;
  2574.   if (contextualActionOpen && (selectedTabs.length < 2)) {
  2575.     document.getElementById("context-opentab").setAttribute("hidden", false);
  2576.     showMainSeparator = true;
  2577.   }
  2578.   if (contextualActionShowcaseThis && globalMode && (selectedTabs.length < 2)) {
  2579.     document.getElementById("showcaseMenuItem").setAttribute("hidden", false);
  2580.     /*
  2581.     if (processedWindows.length < 2) {
  2582.       document.getElementById("cmd_showcasethis").setAttribute("disabled", true);
  2583.     } else {
  2584.       document.getElementById("cmd_showcasethis").setAttribute("disabled", false);
  2585.     }
  2586.     */
  2587.     showMainSeparator = true;
  2588.   }
  2589.   if (showMainSeparator) {
  2590.     lastSeparator = document.getElementById("openTabSeparator");
  2591.     lastSeparator.setAttribute("hidden", false);
  2592.   }
  2593.  
  2594.   // Navigation actions
  2595.   var showNavigationSeparator = false;
  2596.   if (selectedTabs.length < 2) {
  2597.     if (contextualActionBack) {
  2598.       document.getElementById("context-back").setAttribute("hidden", false);
  2599.  
  2600.       var backCommand = document.getElementById("Browser:Back");
  2601.       var backDisabled = backCommand.hasAttribute("disabled");
  2602.     
  2603.       if (backDisabled == showcasePopupTab.targetTab.canGoBack) {
  2604.         if (backDisabled)
  2605.           backCommand.removeAttribute("disabled");
  2606.         else
  2607.           backCommand.setAttribute("disabled", true);
  2608.       }
  2609.  
  2610.       showNavigationSeparator = true;
  2611.     }
  2612.  
  2613.     if (contextualActionForward) {
  2614.       document.getElementById("context-forward").setAttribute("hidden", false);
  2615.  
  2616.       var forwardCommand = document.getElementById("Browser:Forward");
  2617.       var forwardDisabled = forwardCommand.hasAttribute("disabled");
  2618.     
  2619.       if (forwardDisabled == showcasePopupTab.targetTab.canGoForward) {
  2620.         if (forwardDisabled)
  2621.           forwardCommand.removeAttribute("disabled");
  2622.         else
  2623.           forwardCommand.setAttribute("disabled", true);
  2624.       }
  2625.  
  2626.       showNavigationSeparator = true;
  2627.     }
  2628.  
  2629.     if (contextualActionReload) {
  2630.       document.getElementById("context-reload").setAttribute("hidden", false);
  2631.  
  2632.       var reloadCommand = document.getElementById("Browser:Reload");
  2633.       var location;
  2634.       if (showcasePopupTab.targetTab.currentURI) {
  2635.         location = showcasePopupTab.targetTab.currentURI.spec;
  2636.       } else {
  2637.         location = "about:blank";
  2638.       }
  2639.  
  2640.       if (location == "about:blank" || location == "") {
  2641.         reloadCommand.setAttribute("disabled", true);
  2642.       } else {
  2643.         reloadCommand.removeAttribute("disabled");
  2644.       }
  2645.     
  2646.       showNavigationSeparator = true;
  2647.     }
  2648.  
  2649.     if (contextualActionStop) {
  2650.       document.getElementById("context-stop").setAttribute("hidden", false);
  2651.  
  2652.       var stopCommand = document.getElementById("Browser:Stop");
  2653.       if (showcasePopupTab.showcaseProgressListener.progressListener.isLoading) {
  2654.         stopCommand.removeAttribute("disabled");
  2655.       } else {
  2656.         stopCommand.setAttribute("disabled", true);
  2657.       }
  2658.       showNavigationSeparator = true;
  2659.     }
  2660.   } else {
  2661.     if (contextualActionReload) {
  2662.       document.getElementById("context-reload").setAttribute("hidden", false);
  2663.  
  2664.       var activeReload = false;
  2665.       for (var c=0; (c<selectedTabs.length) && !activeReload; c++) {
  2666.         var location = selectedTabs[c].targetTab.contentDocument.URL;
  2667.         if (location != "about:blank" && location != "") {
  2668.           activeReload = true;
  2669.         }
  2670.       }
  2671.  
  2672.       var reloadCommand = document.getElementById("Browser:Reload");
  2673.       if (activeReload) {
  2674.         reloadCommand.removeAttribute("disabled");
  2675.       } else {
  2676.         reloadCommand.setAttribute("disabled", true);
  2677.       }
  2678.     
  2679.       showNavigationSeparator = true;
  2680.     }
  2681.   }
  2682.  
  2683.   if (showNavigationSeparator) {
  2684.     lastSeparator = document.getElementById("navigationSeparator");
  2685.     lastSeparator.setAttribute("hidden", false);
  2686.   }
  2687.  
  2688.   // Tool actions
  2689.   var showToolsSeparator = false;
  2690.  
  2691.   if (selectedTabs.length > 1) {
  2692.     if (contextualActionDuplicateSelected) {
  2693.       document.getElementById("duplicateSelected").setAttribute("hidden", false);
  2694.       showToolsSeparator = true;
  2695.     }
  2696.  
  2697.     if (contextualActionMergeSelected) {
  2698.       document.getElementById("mergeSelected").setAttribute("hidden", false);
  2699.       showToolsSeparator = true;
  2700.     }
  2701.  
  2702.     if (contextualActionBookmarkSelected) {
  2703.       document.getElementById("bookmarkSelectedTabs").setAttribute("hidden", false);
  2704.       showToolsSeparator = true;
  2705.     }
  2706.   } else {
  2707.     if (contextualActionBookmarkPage) {
  2708.       document.getElementById("context-bookmarkpage").setAttribute("hidden", false);
  2709.       showToolsSeparator = true;
  2710.     }
  2711.   
  2712.     if (contextualActionSavePage) {
  2713.       document.getElementById("context-savepage").setAttribute("hidden", false);
  2714.       showToolsSeparator = true;
  2715.     }
  2716.   
  2717.     if (contextualActionSendPage) {
  2718.       document.getElementById("context-sendpage").setAttribute("hidden", false);
  2719.       showToolsSeparator = true;
  2720.     }
  2721.   
  2722.     if (contextualActionPrint) {
  2723.       document.getElementById("print").setAttribute("hidden", false);
  2724.       showToolsSeparator = true;
  2725.     }
  2726.  
  2727.     if (contextualActionViewSource) {
  2728.       document.getElementById("viewSource").setAttribute("hidden", false);
  2729.       showToolsSeparator = true;
  2730.     }
  2731.  
  2732.     if (contextualActionPageInfo) {
  2733.       document.getElementById("pageInfo").setAttribute("hidden", false);
  2734.       showToolsSeparator = true;
  2735.     }
  2736.  
  2737.     if (contextualActionDuplicateTab) {
  2738.       document.getElementById("duplicateTab").setAttribute("hidden", false);
  2739.       showToolsSeparator = true;
  2740.     }
  2741.  
  2742.     if (contextualActionMoveTab) {
  2743.       document.getElementById("moveTab").setAttribute("hidden", false);
  2744.       showToolsSeparator = true;
  2745.     }
  2746.   }
  2747.   
  2748.   if (showToolsSeparator) {
  2749.     lastSeparator = document.getElementById("toolsSeparator");
  2750.     lastSeparator.setAttribute("hidden", false);
  2751.   }
  2752.  
  2753.   // Close actions
  2754.   var hideLastSeparator = true;
  2755.  
  2756.   if (selectedTabs.length < 2) {
  2757.     var found = false;
  2758.     var targetWindow;
  2759.     for (var c=0; ((c<processedWindows.length) && !found); c++) {
  2760.       if (processedWindows[c].processedTabs.indexOf(showcasePopupTab) > -1) {
  2761.         targetWindow = processedWindows[c];
  2762.         found = true;
  2763.       }
  2764.     }
  2765.  
  2766.     if (found) {
  2767.       // Modify popup options depending of item
  2768.       var tabbrowser = targetWindow.targetWindow.getBrowser();
  2769.  
  2770.       if (tabbrowser.mTabContainer.childNodes.length > 1) {
  2771.         // Hide popupclose, show popupclosetab and popupclosewindow
  2772.         if (contextualActionCloseTab) {
  2773.           document.getElementById("popupCloseTab").setAttribute("hidden", false);
  2774.           hideLastSeparator = false;
  2775.         }
  2776.         if (contextualActionCloseWindow) {
  2777.           document.getElementById("popupCloseWindow").setAttribute("hidden", false);
  2778.           hideLastSeparator = false;
  2779.         }
  2780.       } else {
  2781.         if (contextualActionCloseWindow && closeLastTabKeepOpen) {
  2782.           document.getElementById("popupCloseWindow").setAttribute("hidden", false);
  2783.           hideLastSeparator = false;
  2784.         }
  2785.  
  2786.         // show popupclose
  2787.         if (contextualActionClose) {
  2788.           document.getElementById("popupClose").setAttribute("hidden", false);
  2789.           hideLastSeparator = false;
  2790.         }
  2791.       }
  2792.     } else {
  2793.       // Show simple close option
  2794.         if (contextualActionCloseTab) {
  2795.           document.getElementById("popupCloseTab").setAttribute("hidden", false);
  2796.           hideLastSeparator = false;
  2797.         }
  2798.         if (contextualActionCloseWindow) {
  2799.           document.getElementById("popupCloseWindow").setAttribute("hidden", false);
  2800.           hideLastSeparator = false;
  2801.         }
  2802.     }
  2803.   } else {
  2804.     if (contextualActionClose) {
  2805.       document.getElementById("popupClose").setAttribute("hidden", false);
  2806.       hideLastSeparator = false;
  2807.     }
  2808.   }
  2809.  
  2810.   if (contextualActionCloseOther) {
  2811.     document.getElementById("popupCloseOther").setAttribute("hidden", false);
  2812.     hideLastSeparator = false;
  2813.   }
  2814.  
  2815.   if (hideLastSeparator && lastSeparator) {
  2816.     lastSeparator.setAttribute("hidden", true);
  2817.   }
  2818. }
  2819.  
  2820. function enterZoomMode(targetTab) {
  2821.   if (inZoomMode) {
  2822.     return;
  2823.   }
  2824.  
  2825.   inZoomMode = true;
  2826.   zoomTargetThumbnail = targetTab;
  2827.   if (!zoomFitsScreen) {
  2828.     // Reset canvas!
  2829.     zoomTargetThumbnail.showcaseCanvas.showcasePainted = false;
  2830.   }
  2831.   zoomTargetPreviousCursorStyle = zoomTargetThumbnail.showcaseCanvas.style.cursor;
  2832.   zoomTargetThumbnail.showcaseCanvas.style.cursor = "-moz-zoom-in";
  2833.   zoomOffsetX = 0;
  2834.   zoomOffsetY = 0;
  2835.  
  2836.   // Move it a bit...
  2837.   zoomTargetThumbnail.showcaseCanvasBox.setAttribute("top", zoomTargetThumbnail.showcaseCanvasBox.getAttribute("top") - 1);
  2838.   zoomTargetThumbnail.showcaseCanvasBox.setAttribute("left", zoomTargetThumbnail.showcaseCanvasBox.getAttribute("left") - 1);
  2839.  
  2840.   // Make other thumbnails invisible
  2841.   for (var i = 0; i < processedWindows.length; i++) {
  2842.     var targetWindow =  processedWindows[i];
  2843.     for (var j = 0; j<targetWindow.processedTabs.length; j++) {
  2844.       var currentTab = targetWindow.processedTabs[j];
  2845.       if (currentTab != zoomTargetThumbnail) {
  2846.         currentTab.showcaseCanvasBox.hidden = true;
  2847.       }
  2848.     }
  2849.   }
  2850.  
  2851.   // Remember scroll
  2852.   if (scrollBoxObject) {
  2853.     previousZoomScrollX = {};
  2854.     previousZoomScrollY = {};
  2855.     scrollBoxObject.getPosition(previousZoomScrollX, previousZoomScrollY);
  2856.   }
  2857.   
  2858.   refreshContent();
  2859.  
  2860.   checkScrollCursorsVisibility();
  2861. }
  2862.  
  2863. function leaveZoomMode() {
  2864.   if (!inZoomMode) {
  2865.     return;
  2866.   }
  2867.  
  2868.   // Move it a bit...
  2869.   zoomTargetThumbnail.showcaseCanvasBox.setAttribute("top", zoomTargetThumbnail.showcaseCanvasBox.getAttribute("top") - 1);
  2870.   zoomTargetThumbnail.showcaseCanvasBox.setAttribute("left", zoomTargetThumbnail.showcaseCanvasBox.getAttribute("left") - 1);
  2871.  
  2872.  
  2873.   inZoomMode = false;
  2874.   zoomTargetThumbnail.showcaseCanvas.style.cursor = zoomTargetPreviousCursorStyle;
  2875.   if (!zoomFitsScreen) {
  2876.     // Reset canvas!
  2877.     zoomTargetThumbnail.showcaseCanvas.showcasePainted = false;
  2878.   }
  2879.   zoomTargetPreviousCursorStyle = null;
  2880.   zoomTargetThumbnail = null;
  2881.  
  2882.   // Make other thumbnails visible
  2883.   for (var i = 0; i < processedWindows.length; i++) {
  2884.     var targetWindow =  processedWindows[i];
  2885.     for (var j = 0; j<targetWindow.processedTabs.length; j++) {
  2886.       var currentTab = targetWindow.processedTabs[j];
  2887.       if (currentTab != zoomTargetThumbnail) {
  2888.         currentTab.showcaseCanvasBox.hidden = false;
  2889.       }
  2890.     }
  2891.   }
  2892.  
  2893.   checkScrollCursorsVisibility();
  2894.  
  2895.   refreshContent();
  2896.  
  2897.   // Restore zoom
  2898.   if (scrollBoxObject != null) {
  2899.     setTimeout(scrollBoxObject.scrollTo, 0, previousZoomScrollX.value, previousZoomScrollY.value);
  2900.   }
  2901. }
  2902.  
  2903. function checkScrollCursorsVisibility() {
  2904.   if (!zoomCursorLeft) {
  2905.     zoomCursorLeft = document.getElementById("cursor-left");
  2906.     zoomCursorRight = document.getElementById("cursor-right");
  2907.     zoomCursorUp = document.getElementById("cursor-up");
  2908.     zoomCursorDown = document.getElementById("cursor-down");
  2909.   }
  2910.  
  2911.   if (inZoomMode && (renderingType == 0) && (zoomScrollIncrement != 0) && (!zoomTargetThumbnail.showcaseImage) && (!zoomTargetThumbnail.showcaseEmbedded)) {
  2912.     // Check...
  2913.     if (zoomTargetThumbnail.targetTab) {
  2914.       var targetView = zoomTargetThumbnail.targetTab.contentWindow;
  2915.       if ((targetView.scrollY > 0) || (!zoomFitsScreen && (zoomOffsetY > 0))) {
  2916.         zoomCursorUp.removeAttribute("hidden");
  2917.       } else {
  2918.         zoomCursorUp.setAttribute("hidden", true);
  2919.         zoomScrollingUp = false;
  2920.       }
  2921.       if ((targetView.scrollY < targetView.scrollMaxY) || (!zoomFitsScreen && (zoomOffsetY < (zoomTotalHeight - zoomCurrentHeight)))) {
  2922.         zoomCursorDown.removeAttribute("hidden");
  2923.       } else {
  2924.         zoomCursorDown.setAttribute("hidden", true);
  2925.         zoomScrollingDown = false;
  2926.       }
  2927.       if ((targetView.scrollX > 0) || (!zoomFitsScreen && (zoomOffsetX > 0))) {
  2928.         zoomCursorLeft.removeAttribute("hidden");
  2929.       } else {
  2930.         zoomCursorLeft.setAttribute("hidden", true);
  2931.         zoomScrollingLeft = false;
  2932.       }
  2933.       if ((targetView.scrollX < targetView.scrollMaxX) || (!zoomFitsScreen && (zoomOffsetX < (zoomTotalWidth - zoomCurrentWidth)))) {
  2934.         zoomCursorRight.removeAttribute("hidden");
  2935.       } else {
  2936.         zoomCursorRight.setAttribute("hidden", true);
  2937.         zoomScrollingRight = false;
  2938.       }
  2939.     }
  2940.   } else {
  2941.     zoomCursorUp.setAttribute("hidden", true);
  2942.     zoomCursorDown.setAttribute("hidden", true);
  2943.     zoomCursorLeft.setAttribute("hidden", true);
  2944.     zoomCursorRight.setAttribute("hidden", true);
  2945.     zoomScrollingUp = false;
  2946.     zoomScrollingDown = false;
  2947.     zoomScrollingLeft = false;
  2948.     zoomScrollingRight = false;
  2949.   }
  2950. }
  2951.  
  2952. function doZoomScrollUp() {
  2953.   if (inZoomMode && zoomScrollingUp) {
  2954.     zoomPanUp(zoomScrollIncrement);
  2955.     setTimeout(function foo(a) { a.doZoomScrollUp() }, 20, this);
  2956.   }
  2957. }
  2958.  
  2959. function doZoomScrollDown() {
  2960.   if (inZoomMode && zoomScrollingDown) {
  2961.     zoomPanDown(zoomScrollIncrement);
  2962.     setTimeout(function foo(a) { a.doZoomScrollDown() }, 20, this);
  2963.   }
  2964. }
  2965.  
  2966. function doZoomScrollLeft() {
  2967.   if (inZoomMode && zoomScrollingLeft) {
  2968.     zoomPanLeft(zoomScrollIncrement);
  2969.     setTimeout(function foo(a) { a.doZoomScrollLeft() }, 20, this);
  2970.   }
  2971. }
  2972.  
  2973. function doZoomScrollRight() {
  2974.   if (inZoomMode && zoomScrollingRight) {
  2975.     zoomPanRight(zoomScrollIncrement);
  2976.     setTimeout(function foo(a) { a.doZoomScrollRight() }, 20, this);
  2977.   }
  2978. }
  2979.  
  2980. function zoomPanLeft(increment) {
  2981.     if (!zoomFitsScreen && (zoomOffsetX > 0)) {
  2982.       zoomOffsetX -= increment;
  2983.       if ((zoomOffsetX < 0) && (zoomTargetThumbnail.targetTab.contentWindow.scrollX > 0)) {
  2984.         increment = -zoomOffsetX;
  2985.         zoomOffsetX = 0;
  2986.       } else {
  2987.         increment = 0;
  2988.         // Refresh thumbnail
  2989.         zoomTargetThumbnail.showcaseCanvas.showcasePainted = false;
  2990.         setTimeout(function foo(a) { paintThumbnail(a); checkScrollCursorsVisibility(); }, 0, zoomTargetThumbnail);
  2991.       }
  2992.     }
  2993.     if (increment != 0) {
  2994.       zoomTargetThumbnail.targetTab.contentWindow.scrollBy(-increment, 0);
  2995.     }
  2996. }
  2997.  
  2998. function zoomPanRight(increment) {
  2999.     if (!zoomFitsScreen && (zoomOffsetX < (zoomTotalWidth - zoomCurrentWidth))) {
  3000.       zoomOffsetX += increment;
  3001.       if ((zoomOffsetX > (zoomTotalWidth - zoomCurrentWidth)) && (zoomTargetThumbnail.targetTab.contentWindow.scrollX < zoomTargetThumbnail.targetTab.contentWindow.scrollMaxX)) {
  3002.         increment = zoomOffsetX - (zoomTotalWidth - zoomCurrentWidth);
  3003.         zoomOffsetX = (zoomTotalWidth - zoomCurrentWidth);
  3004.       } else {
  3005.         increment = 0;
  3006.         // Refresh thumbnail
  3007.         zoomTargetThumbnail.showcaseCanvas.showcasePainted = false;
  3008.         setTimeout(function foo(a) { paintThumbnail(a); checkScrollCursorsVisibility(); }, 0, zoomTargetThumbnail);
  3009.       }
  3010.     }
  3011.     if (increment != 0) {
  3012.       zoomTargetThumbnail.targetTab.contentWindow.scrollBy(increment, 0);
  3013.     }
  3014. }
  3015.  
  3016. function zoomPanUp(increment) {
  3017.   if (!zoomFitsScreen && (zoomOffsetY > 0)) {
  3018.     zoomOffsetY -= increment;
  3019.     if ((zoomOffsetY < 0) && (zoomTargetThumbnail.targetTab.contentWindow.scrollY > 0)) {
  3020.       increment = -zoomOffsetY;
  3021.       zoomOffsetY = 0;
  3022.     } else {
  3023.       increment = 0;
  3024.       // Refresh thumbnail
  3025.       zoomTargetThumbnail.showcaseCanvas.showcasePainted = false;
  3026.       setTimeout(function foo(a) { paintThumbnail(a); checkScrollCursorsVisibility(); }, 0, zoomTargetThumbnail);
  3027.     }
  3028.   }
  3029.   if (increment != 0) {
  3030.     zoomTargetThumbnail.targetTab.contentWindow.scrollBy(0, -increment);
  3031.   }
  3032. }
  3033.  
  3034. function zoomPanDown(increment) {
  3035.   if (!zoomFitsScreen && (zoomOffsetY < (zoomTotalHeight - zoomCurrentHeight))) {
  3036.     zoomOffsetY += increment;
  3037.     if ((zoomOffsetY < (zoomTotalHeight - zoomCurrentHeight)) && (zoomTargetThumbnail.targetTab.contentWindow.scrollY < zoomTargetThumbnail.targetTab.contentWindow.scrollMaxY)) {
  3038.       increment = zoomOffsetY - (zoomTotalHeight - zoomCurrentHeight);
  3039.       zoomOffsetY = zoomTotalHeight - zoomCurrentHeight;
  3040.     } else {
  3041.       increment = 0;
  3042.       // Refresh thumbnail
  3043.       zoomTargetThumbnail.showcaseCanvas.showcasePainted = false;
  3044.       setTimeout(function foo(a) { paintThumbnail(a); checkScrollCursorsVisibility(); }, 0, zoomTargetThumbnail);
  3045.     }
  3046.   }
  3047.   if (increment != 0) {
  3048.     zoomTargetThumbnail.targetTab.contentWindow.scrollBy(0, increment);
  3049.   }
  3050. }
  3051.  
  3052. function thumbnailFocus(el) {
  3053.   if (currentCursor != el.target.showcaseTab) {
  3054.     processFocusedTab(el.target.showcaseTab);
  3055.  
  3056.     // Ensure it's visible
  3057.     ensureThumbnailIsVisible(el.target);
  3058.   }
  3059. }
  3060.  
  3061. function ensureThumbnailIsVisible(targetThumbnail) {
  3062.   if (scrollBoxObject) {
  3063.     var targetBoxObject = targetThumbnail.boxObject;
  3064.     var scrollX = {};
  3065.     var scrollY = {};
  3066.     scrollBoxObject.getPosition(scrollX,scrollY);
  3067.     var newX = scrollX.value;
  3068.     var newY = scrollY.value;
  3069.     var boxX = parseInt(targetThumbnail.getAttribute("left"));
  3070.     var boxY = parseInt(targetThumbnail.getAttribute("top"));
  3071.  
  3072.     if ((boxX + targetBoxObject.width - scrollX.value - scrollBoxObject.width) > 0) {
  3073.       newX = targetBoxObject.width + boxX - scrollBoxObject.width;
  3074.     }
  3075.     if ((boxY + targetBoxObject.height - scrollY.value - scrollBoxObject.height) > 0) {
  3076.       newY = targetBoxObject.height + boxY - scrollBoxObject.height;
  3077.     }
  3078.  
  3079.     if ((boxX - scrollX.value) < 0) {
  3080.       newX = boxX - 1;
  3081.     }
  3082.     if ((boxY - scrollY.value) < 0) {
  3083.       newY = boxY - 1;
  3084.     }
  3085.     if ((newX != scrollX.value) || (newY != scrollY.value))
  3086.       scrollBoxObject.scrollTo(newX, newY);
  3087.   }
  3088. }
  3089.  
  3090. function isThumbnailVisible(targetThumbnail) {
  3091.   if (scrollBoxObject) {
  3092.     var targetBoxObject = targetThumbnail.boxObject;
  3093.     var scrollX = {};
  3094.     var scrollY = {};
  3095.     scrollBoxObject.getPosition(scrollX,scrollY);
  3096.     var newX = scrollX.value;
  3097.     var newY = scrollY.value;
  3098.     var boxX = parseInt(targetThumbnail.getAttribute("left"));
  3099.     var boxY = parseInt(targetThumbnail.getAttribute("top"));
  3100.  
  3101.     if ((boxX + targetBoxObject.width - scrollX.value - scrollBoxObject.width) > 0) {
  3102.       return false;
  3103.     }
  3104.     if ((boxY + targetBoxObject.height - scrollY.value - scrollBoxObject.height) > 0) {
  3105.       return false;
  3106.     }
  3107.  
  3108.     if ((boxX - scrollX.value) < 0) {
  3109.       return false;
  3110.     }
  3111.     if ((boxY - scrollY.value) < 0) {
  3112.       return false;
  3113.     }
  3114.   }
  3115.   
  3116.   return true;
  3117. }
  3118.  
  3119.  
  3120. function ensureSelectedThumbnailVisible(targetProcessedWindow) {
  3121.   // Get selected tab
  3122.   var tabbrowser = targetProcessedWindow.targetWindow.getBrowser();
  3123.   var tabs = tabbrowser.mTabContainer.childNodes;
  3124.   var selectedTab = tabbrowser.getBrowserForTab(tabs[tabbrowser.mTabContainer.selectedIndex]);
  3125.   var found = false;
  3126.  
  3127.   // Iterate array
  3128.   for (var c=0; ((c<targetProcessedWindow.processedTabs.length) && !found); c++) {
  3129.     var processedTab = targetProcessedWindow.processedTabs[c];
  3130.     
  3131.     if (processedTab.targetTab == selectedTab) {
  3132.       ensureThumbnailIsVisible(processedTab.showcaseCanvasBox);
  3133.     }
  3134.   }
  3135. }
  3136.  
  3137. function processFocusedTab(targetProcessedTab) {
  3138.   if (focusToggleSelection) {
  3139.     toggleSelection(targetProcessedTab);
  3140.   } else if (focusSelectRange) {
  3141.     if (lastFocusedTab == null) {
  3142.       // Add only the new focused cursor...
  3143.       addToSelection(targetProcessedTab);
  3144.     } else {
  3145.       // Add the range between both elements...
  3146.       addRangeToSelection(lastFocusedTab, targetProcessedTab);
  3147.     }
  3148.   } else if (focusSelectIfUnselected) {
  3149.     if (selectedTabs.indexOf(targetProcessedTab) < 0) {
  3150.       removeAllSelections();
  3151.       addToSelection(targetProcessedTab);
  3152.     }
  3153.   } else if (!focusIgnoreSelection) {
  3154.     removeAllSelections();
  3155.     addToSelection(targetProcessedTab);
  3156.   }
  3157.   
  3158.   focusToggleSelection = false;
  3159.   focusSelectRange = false;
  3160.   focusSelectIfUnselected = false;
  3161.   focusIgnoreSelection = false;
  3162.  
  3163.   currentCursor = targetProcessedTab;
  3164. }
  3165.  
  3166. function thumbnailBlur(el) {
  3167.   if ((currentCursor == el.target.showcaseTab) && (document.commandDispatcher.focusedElement != el.target)) {
  3168.     lastFocusedTab = currentCursor;
  3169.     currentCursor = null;
  3170.   }
  3171. }
  3172.  
  3173. function addRangeToSelection(fromTab, toTab) {
  3174.   var foundFirst = false;
  3175.   var foundLast = false;
  3176.  
  3177.   for (var c=0; (c<processedWindows.length)&&!foundLast; c++) {
  3178.     for (var d=0; (d<processedWindows[c].processedTabs.length)&&!foundLast; d++) {
  3179.       if (!foundFirst) {
  3180.         if ((processedWindows[c].processedTabs[d] == fromTab) || 
  3181.             (processedWindows[c].processedTabs[d] == toTab)) {
  3182.           addToSelection(processedWindows[c].processedTabs[d]);
  3183.           foundFirst = true;
  3184.         }
  3185.       } else if (!foundLast) {
  3186.         addToSelection(processedWindows[c].processedTabs[d]);
  3187.         if ((processedWindows[c].processedTabs[d] == fromTab) || 
  3188.             (processedWindows[c].processedTabs[d] == toTab)) {
  3189.           foundLast = true;
  3190.         }
  3191.       }
  3192.     }
  3193.   }
  3194. }
  3195.  
  3196. function toggleSelection(targetProcessedTab) {
  3197.   if (selectedTabs.indexOf(targetProcessedTab) > -1) {
  3198.     removeFromSelection(targetProcessedTab);
  3199.   } else {
  3200.     addToSelection(targetProcessedTab);
  3201.   }
  3202. }
  3203.  
  3204. function removeFromSelection(targetProcessedTab) {
  3205.   var targetIndex = selectedTabs.indexOf(targetProcessedTab);
  3206.   if (targetIndex > -1) {
  3207.     targetProcessedTab.showcaseCanvasBox.removeAttribute("selected");
  3208.     removeElementAt(selectedTabs, targetIndex);
  3209.   }
  3210. }
  3211.  
  3212. function addToSelection(targetProcessedTab) {
  3213.   if (selectedTabs.indexOf(targetProcessedTab) < 0) {
  3214.     selectedTabs.push(targetProcessedTab);
  3215.     targetProcessedTab.showcaseCanvasBox.setAttribute("selected", "true");
  3216.   }
  3217. }
  3218.  
  3219. function removeAllSelections() {
  3220.   while (selectedTabs.length > 0) {
  3221.     var currentTab = selectedTabs.shift();
  3222.     currentTab.showcaseCanvasBox.removeAttribute("selected");
  3223.   }
  3224. }
  3225.  
  3226. function selectAll() {
  3227.   removeAllSelections();
  3228.   for (var c=0; c<processedWindows.length; c++) {
  3229.     for (var d=0; d<processedWindows[c].processedTabs.length; d++) {
  3230.       if (!processedWindows[c].processedTabs[d].showcaseCanvasBox.hidden) {
  3231.         addToSelection(processedWindows[c].processedTabs[d]);
  3232.       }
  3233.     }
  3234.   }
  3235. }
  3236.  
  3237. function refreshFocus(targetElement) {
  3238.   targetElement.focus();
  3239. }
  3240.  
  3241. function mouseOverCanvas(el) {
  3242.   var hasEntered = true;
  3243.   var currentNode = el.relatedTarget;
  3244.  
  3245.   if (currentNode) {
  3246.     while (hasEntered && currentNode.parentNode) {
  3247.       hasEntered = (el.currentTarget != currentNode.parentNode);
  3248.       currentNode = currentNode.parentNode;
  3249.     }
  3250.   }
  3251.  
  3252.   if (hasEntered) {
  3253.     if (thumbnailActiveAnimation) {
  3254.       animateBox(el.currentTarget, true);
  3255.     } else {
  3256.       // Show thumbnail icons
  3257.       setCurrentIconsThumbnail(el.currentTarget);
  3258.     }
  3259.  
  3260.     if (selectWhenMouseOver) {
  3261.       var targetBox;
  3262.       if (el.currentTarget.showcaseCanvas) { 
  3263.         targetBox = el.currentTarget.showcaseCanvas.showcaseCanvasBox;
  3264.       } else {
  3265.         targetBox = el.currentTarget.showcaseCanvasBox;
  3266.       }
  3267.  
  3268.       if (selectWhenMouseOverDelay > 0) {
  3269.         if (selectTimer == null) {
  3270.           selectTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
  3271.         }
  3272.         selectTimer.cancel();
  3273.         selectTimerTarget = targetBox;
  3274.  
  3275.         var selectTimerNotifier = {
  3276.           QueryInterface : function (aIID) {
  3277.             if (aIID.equals(Components.interfaces.nsITimerCallback) ||
  3278.                 aIID.equals(Components.interfaces.nsISupports) ||
  3279.                 aIID.equals(Components.interfaces.nsISupportsWeakReference))
  3280.               return this;
  3281.             throw Components.results.NS_NOINTERFACE;
  3282.           },
  3283.  
  3284.           notify: function(timer) {
  3285.             if (selectTimerTarget && !selectTimerTarget.hasAttribute("selectedtab")) {
  3286.               openTab(selectTimerTarget.showcaseTab);
  3287.             }
  3288.           }
  3289.         };
  3290.  
  3291.         selectTimer.initWithCallback(selectTimerNotifier, selectWhenMouseOverDelay, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
  3292.       } else {
  3293.         if (!targetBox.hasAttribute("selectedtab")) {
  3294.           openTab(targetBox.showcaseTab);
  3295.         }
  3296.       }
  3297.     }
  3298.   }
  3299. }
  3300.  
  3301. function mouseOutCanvas(el) {
  3302.   var hasExited = true;
  3303.   var currentNode = el.relatedTarget;
  3304.  
  3305.   lastMouseDownTab = null;
  3306.  
  3307.   if (currentNode) {
  3308.     while (hasExited && currentNode.parentNode) {
  3309.       hasExited = ((el.currentTarget != currentNode.parentNode) && (!currentNode.hasAttribute("class") || currentNode.getAttribute("class") != "thumb-icon"));
  3310.       currentNode = currentNode.parentNode;
  3311.     }
  3312.   }
  3313.  
  3314.   if (hasExited) {
  3315.     if (currentIconsThumbnail == el.currentTarget) {
  3316.       hideThumbnailIcons();
  3317.       currentIconsThumbnail = null;
  3318.     }
  3319.  
  3320.     if (thumbnailActiveAnimation) {
  3321.       animateBox(el.currentTarget, false);
  3322.     }
  3323.     if (selectTimer) {
  3324.       selectTimer.cancel();
  3325.       selectTimerTarget = null;
  3326.     }
  3327.   }
  3328. }
  3329.  
  3330. function mouseDownCanvas(el) {
  3331.   // Zoom mode
  3332.   var targetTab = el.currentTarget.showcaseTab;
  3333.  
  3334.   lastMouseDownTab = targetTab;
  3335.  
  3336.   if ((el.button == 2) && (rightClickAction == 4)) {
  3337.     focusSelectIfUnselected = true;
  3338.   } else if (el.ctrlKey || el.shiftKey) {
  3339.     if (el.ctrlKey) {
  3340.       focusIgnoreSelection = true;
  3341.     } else { // if (el.shiftKey) {
  3342.       focusSelectRange = true;
  3343.     }
  3344.   } else if ((el.button >= 0) && (el.button <= 2)) {
  3345.     var clickAction;
  3346.     
  3347.     if (el.button == 0) {
  3348.       clickAction = leftClickAction;
  3349.     } else if (el.button == 1) {
  3350.       clickAction = middleClickAction;
  3351.     } else { // if (el.button == 2) {
  3352.       clickAction = rightClickAction;
  3353.     }
  3354.  
  3355.     if (clickAction == 1) { 
  3356.       focusIgnoreSelection = true;
  3357.       enterZoomMode(targetTab);
  3358.  
  3359.       if (topWindow != window) {
  3360.         el.stopPropagation();
  3361.         el.preventDefault();
  3362.       }
  3363.     } else {
  3364.       if (selectedTabs.indexOf(targetTab) > -1) {
  3365.         focusIgnoreSelection = true;
  3366.       }
  3367.       if (clickAction == 2) {
  3368.         if (!selectWhenOpen) {
  3369.           focusIgnoreSelection = true;
  3370.         }
  3371.         if ((topWindow != window) && (el.button != 0)) {
  3372.           el.stopPropagation();
  3373.           el.preventDefault();
  3374.         }
  3375.       }
  3376.     }
  3377.   }
  3378.   if ((targetTab) && (targetTab == currentCursor)) {
  3379.     processFocusedTab(currentCursor);
  3380.   }
  3381. }
  3382.  
  3383. function mouseDblClickWindow(el) {
  3384.   if (el.originalTarget == showcaseBox) {
  3385.     // If double clicking on box check the double click action
  3386.     switch (doubleClickAction) {
  3387.       case 0:
  3388.         // select all thumbnails
  3389.         selectAll();
  3390.         break;
  3391.       case 1:
  3392.         // Open new tab
  3393.         var currentMosaicCol = Math.floor(el.layerX * mosaicColumns / mosaicWidth);
  3394.         var currentMosaicRow = Math.floor(el.layerY * mosaicRows / mosaicHeight);
  3395.         var targetTab = getTabAt(currentMosaicRow, currentMosaicCol);
  3396.         currentMosaicCol = targetTab.showcaseColumn;
  3397.         currentMosaicRow = targetTab.showcaseRow;
  3398.         var atLeftSide = ((el.layerX - currentMosaicCol * mosaicWidth / mosaicColumns) < (mosaicWidth / (mosaicColumns * 2)))
  3399.         openNewTab(targetTab, atLeftSide);        
  3400.         break;
  3401.       case 2:
  3402.         // Close showcase
  3403.         showcaseCloseWindow();
  3404.         break;
  3405.     }
  3406.   }
  3407. }
  3408.  
  3409. function openNewTab(targetShowcaseTab, atLeftSide) {
  3410.   var targetWindow = targetShowcaseTab.targetTabWindow.targetWindow;
  3411.   var newTab;
  3412.   var tabbrowser = targetWindow.getBrowser();
  3413.   var targetIndex;
  3414.   
  3415.   if (targetWindow.SpeedDial && gPref.getBoolPref("extensions.speeddial.loadInNewTab")) {
  3416.     newTab = tabbrowser.addTab("chrome://speeddial/content/");
  3417.   } else {
  3418.     newTab = tabbrowser.addTab("about:blank");
  3419.   }  
  3420.   
  3421.   
  3422.   targetIndex = targetShowcaseTab.tabHeader._tPos;
  3423.   
  3424.   if (!atLeftSide) {
  3425.     targetIndex++;
  3426.   }
  3427.   
  3428.   tabbrowser.moveTabTo(newTab, targetIndex);
  3429.   
  3430. }
  3431.  
  3432. function mouseUpWindow(el) {
  3433.   if (((el.button == 0) || (el.button == 1) || ((el.button == 2) && (rightClickAction != 4)) ) && !(el.ctrlKey || el.shiftKey)) {
  3434.     var clickAction;
  3435.     if (el.button == 0) {
  3436.       clickAction = leftClickAction;
  3437.     } else if (el.button == 1) {
  3438.       clickAction = middleClickAction;
  3439.     } else { // if (button == 2) {
  3440.       clickAction = rightClickAction;
  3441.     }
  3442.     if (clickAction == 1) { 
  3443.       // Zoom mode
  3444.       leaveZoomMode();
  3445.       if (topWindow != window) {
  3446.         el.stopPropagation();
  3447.       }
  3448.     }
  3449.   }
  3450. }
  3451.  
  3452. function mouseUpCanvas(el) {
  3453.   if (!selectionBox.hasAttribute("hidden")) {
  3454.     return;
  3455.   }
  3456.   var targetProcessedTab = el.currentTarget.showcaseTab;
  3457.   if (((el.button == 0) || (el.button == 1) || ((el.button == 2) && (rightClickAction != 4)) ) && !(el.ctrlKey || el.shiftKey) && (lastMouseDownTab == targetProcessedTab)) {
  3458.     var clickAction;
  3459.  
  3460.     if (el.target != targetProcessedTab.showcaseCanvasBox.showcaseCloseButton) {
  3461.       if (el.button == 0) {
  3462.         clickAction = leftClickAction;
  3463.       } else if (el.button == 1) {
  3464.         clickAction = middleClickAction;
  3465.       } else { // if (el.button == 2) {
  3466.         clickAction = rightClickAction;
  3467.       }
  3468.  
  3469.       if (clickAction == 1) { 
  3470.         // Zoom mode
  3471.         leaveZoomMode();
  3472.       } else if (!((el.button == 2) && (rightClickAction == 4))) {
  3473.         switch (clickAction) { 
  3474.           case 0:
  3475.             // Close
  3476.             closeShowcaseTab(targetProcessedTab);
  3477.             break;
  3478.           case 2:
  3479.             if (!selectWhenOpen) {
  3480.               removeAllSelections();
  3481.             }
  3482.             // Open
  3483.             openTab(targetProcessedTab);
  3484.             break;
  3485.           case 3:
  3486.             // Nothing
  3487.             if ((el.button == 0) && ((selectedTabs.length > 1) || (selectedTabs[0] != targetProcessedTab))) {
  3488.               removeAllSelections();
  3489.               addToSelection(targetProcessedTab);
  3490.             }
  3491.             break;
  3492.         }
  3493.       }
  3494.     }
  3495.   } else if ((el.button == 0) && el.ctrlKey && (lastMouseDownTab == targetProcessedTab)) {
  3496.     var targetProcessedTab = el.currentTarget.showcaseTab;
  3497.     toggleSelection(targetProcessedTab);
  3498.   }
  3499.  
  3500.   lastMouseDownTab = null;
  3501.  
  3502.   if (topWindow != window) {
  3503.     el.preventDefault();
  3504.     el.stopPropagation();
  3505.   }
  3506. }
  3507.  
  3508. function mouseClickClose(el) {
  3509.   if (el.button == 0) {
  3510.     if (el.target.targetProcessedTab) {
  3511.       closeShowcaseTab(el.target.targetProcessedTab);
  3512.     }
  3513.   }
  3514. }
  3515.  
  3516. function mouseDoubleClickCanvas(el) {
  3517.   // As easy as opening the tab
  3518.   if (el.currentTarget.showcaseTab) {
  3519.     openTab(el.currentTarget.showcaseTab);
  3520.   }
  3521. }
  3522.  
  3523. function openTab(targetProcessedTab) {
  3524.   // Look for the tab that has the canvas
  3525.   try {
  3526.     var found = false;
  3527.     var targetProcessedWindow;
  3528.     var targetTabIndex;
  3529.     var targetTabBrowser;
  3530.  
  3531.     for (var i = 0; (i < processedWindows.length) && !found; i++) {
  3532.       var currentWindow = processedWindows[i];
  3533.  
  3534.       if (currentWindow.processedTabs.indexOf(targetProcessedTab) > -1) {
  3535.         targetTabBrowser = currentWindow.targetWindow.getBrowser();
  3536.         
  3537.         found = true;
  3538.         targetProcessedWindow = currentWindow;
  3539.  
  3540.         var foundTab = false;
  3541.         for (var j = 0; (j<targetTabBrowser.tabContainer.childNodes.length) && !foundTab; j++) {
  3542.           var targetTab = targetTabBrowser.getBrowserForTab(targetTabBrowser.tabContainer.childNodes.item(j));
  3543.           if (targetProcessedTab.targetTab == targetTab) {
  3544.             targetTabIndex = j;
  3545.             foundTab = true;
  3546.           }
  3547.         }
  3548.       }
  3549.     }
  3550.  
  3551.     if (found) {
  3552.       if ((targetTabBrowser.tabContainer.selectedIndex == targetTabIndex) && tabFlipping && (targetTabBrowser.previousTab || targetProcessedWindow.targetWindow.flst)) {
  3553.         if (targetTabBrowser.previousTab) {
  3554.           targetTabBrowser.previousTab(targetProcessedTab.tabHeader);
  3555.         } else {
  3556.           targetProcessedWindow.targetWindow.flst.tabFlip();
  3557.         }
  3558.       } else {
  3559.         targetTabBrowser.tabContainer.selectedIndex = targetTabIndex;
  3560.       }
  3561.       
  3562.       if (targetProcessedWindow.targetWindow != topWindow) {
  3563.         if (showcaseCloseWhenSelect) {
  3564.           targetFocusWindow = targetProcessedWindow.targetWindow;
  3565.         } else {
  3566.           try {
  3567.             targetProcessedWindow.targetWindow.focus();
  3568.           } catch (focusEx) {
  3569.             showFocusAlert(targetProcessedWindow.targetWindow);
  3570.           }
  3571.         }
  3572.       } else {
  3573.         targetFocusWindow = null;
  3574.       }
  3575.     } else {
  3576.       // Alert user we haven't found the page
  3577.       // TODO: localized string
  3578.       alert("The selected browser couldn't be found.");
  3579.     }
  3580.  
  3581.     // Last, close ourselves
  3582.     if (showcaseCloseWhenSelect) {
  3583.       showcaseCloseWindow();
  3584.     }
  3585.  
  3586.   } catch (e) {
  3587.     alert("openTab: " + e);
  3588.   }
  3589. }
  3590.  
  3591. function selectTab(targetTabBrowser, targetTabIndex) {
  3592.   targetTabBrowser.tabContainer.selectedIndex = targetTabIndex;
  3593. }
  3594.  
  3595. function showFocusAlert(targetWindow) {
  3596.   try {
  3597.     var showcaseBundle = document.getElementById("bundle_showcase");
  3598.     targetWindow.alert(showcaseBundle.getString("showcase.focus.alert"));
  3599.   } catch (e) {
  3600.     // Fail silently
  3601.   }
  3602. }
  3603.  
  3604. function unloadShowcase() {
  3605.   if (window.opener) {
  3606.     try {
  3607.       // Store window values to remember later
  3608.       var prefs = Components.classes["@mozilla.org/preferences-service;1"].
  3609.                 getService(Components.interfaces.nsIPrefBranch);
  3610.       prefs.setIntPref("extensions.showcase.windowLastX", window.screenX);
  3611.       prefs.setIntPref("extensions.showcase.windowLastY", window.screenY);
  3612.       if (window.innerWidth > 0) {
  3613.         prefs.setIntPref("extensions.showcase.windowLastWidth", window.innerWidth);
  3614.       }
  3615.       if (window.innerHeight > 0) {
  3616.         prefs.setIntPref("extensions.showcase.windowLastHeight", window.innerHeight);
  3617.       }
  3618.       var lastRelativeX = window.screenX - window.opener.screenX;
  3619.       var lastRelativeY = window.screenY - window.opener.screenY;
  3620.       prefs.setIntPref("extensions.showcase.windowLastRelativeX", lastRelativeX);
  3621.       prefs.setIntPref("extensions.showcase.windowLastRelativeY", lastRelativeY);
  3622.     } catch (ex) {
  3623.       // We may have trouble in the case window is closed, so just fail silently
  3624.     }
  3625.   }
  3626.  
  3627.   // Free resources
  3628.   if (!closingShowcase) {
  3629.     closingShowcase = true;
  3630.     unlinkShowcase(CACHEMODE_UPDATE);
  3631.  
  3632.     
  3633.     // Check synch find bar in tab mode
  3634.     if (synchFindBar && (topWindow != window.top) && searchActive) {
  3635.       if (topWindow.openFindBar) {
  3636.         topWindow.openFindBar();
  3637.       } else if (topWindow.gFindBar) {
  3638.         topWindow.gFindBar.openFindBar();
  3639.       }
  3640.     }
  3641.     
  3642.  
  3643.     // See if we've to toggle the find bar...
  3644.  
  3645.     if (targetFocusWindow) {
  3646.       try {
  3647.         targetFocusWindow.focus();
  3648.       } catch (e) {
  3649.         showFocusAlert(targetFocusWindow);
  3650.       }
  3651.     }
  3652.   }
  3653. }
  3654.  
  3655. function animateBox(targetElement, growBox) {
  3656.   var targetBox;
  3657.  
  3658.   if (targetElement.showcaseCanvas) { 
  3659.     targetBox = targetElement.showcaseCanvas.showcaseCanvasBox;
  3660.   } else {
  3661.     targetBox = targetElement.showcaseCanvasBox;
  3662.   }
  3663.  
  3664.   targetBox.showcaseGrowing = growBox;
  3665.   if (currentAnimations.indexOf(targetBox) < 0) {
  3666.     if (growBox) {
  3667.       if (thumbnailActiveSizeFactor > 100) {
  3668.         // Hack to bring it to the front
  3669.         if (showcaseBox.childNodes[showcaseBox.childNodes.length - 2] != targetBox) {
  3670.           targetBox.removeEventListener("mouseover", mouseOverCanvas, false);
  3671.           targetBox.removeEventListener("mouseout", mouseOutCanvas, false);
  3672.           targetBox.removeEventListener("focus", thumbnailFocus, false);
  3673.           targetBox.removeEventListener("blur", thumbnailBlur, false);
  3674.           if (targetBox.showcaseCloseButton) {
  3675.             targetBox.showcaseCloseButton.removeEventListener("click", mouseClickClose, true);
  3676.           }
  3677.           targetBox.removeEventListener("mousedown", mouseDownCanvas, (topWindow != window));
  3678.           targetBox.removeEventListener("mouseup", mouseUpCanvas, (topWindow != window));
  3679.           if (doubleClickOpen) {
  3680.             targetBox.removeEventListener("dblclick", mouseDoubleClickCanvas, (topWindow != window));
  3681.           }
  3682.  
  3683.           showcaseBox.removeChild(targetBox);
  3684.           showcaseBox.insertBefore(targetBox, selectionBox);
  3685.           targetBox.addEventListener("mouseover", mouseOverCanvas, false);
  3686.           targetBox.addEventListener("mouseout", mouseOutCanvas, false);
  3687.           targetBox.addEventListener("focus", thumbnailFocus, false);
  3688.           targetBox.addEventListener("blur", thumbnailBlur, false);
  3689.           if (targetBox.showcaseCloseButton) {
  3690.             targetBox.showcaseCloseButton.addEventListener("click", mouseClickClose, true);
  3691.           }
  3692.           targetBox.addEventListener("mousedown", mouseDownCanvas, (topWindow != window));
  3693.           targetBox.addEventListener("mouseup", mouseUpCanvas, (topWindow != window));
  3694.           if (doubleClickOpen) {
  3695.             targetBox.addEventListener("dblclick", mouseDoubleClickCanvas, (topWindow != window));
  3696.           }
  3697.           if (currentCursor == targetBox.showcaseTab) {
  3698.             focusIgnoreSelection = true;
  3699.             targetBox.focus();
  3700.           }
  3701.         }
  3702.       }
  3703.       targetBox.showcaseAnimationFrame = 0;
  3704.     } else {
  3705.       targetBox.showcaseAnimationFrame = animationFrames;
  3706.     }
  3707.     currentAnimations.push(targetBox);
  3708.   }
  3709. }
  3710.  
  3711. function animationThread() {
  3712.   var checkpointTime = new Date().getTime();
  3713.  
  3714.   if (currentAnimations && (currentAnimations.length > 0)) {
  3715.     var c = 0;
  3716.  
  3717.     while (c < currentAnimations.length) {
  3718.       var currentBox = currentAnimations[c];
  3719.       var endAnimation = false;
  3720.  
  3721.       if (!currentBox.showcaseIdleWidth || !currentBox.showcaseIdleHeight || !currentBox.showcaseActiveWidth ||!currentBox.showcaseActiveHeight) {
  3722.         c++;
  3723.         continue;
  3724.       }
  3725.  
  3726.       if (currentBox.showcaseGrowing) {
  3727.         currentBox.showcaseAnimationFrame++;
  3728.         if (currentBox.showcaseAnimationFrame >= animationFrames) {
  3729.           currentBox.showcaseAnimationFrame = animationFrames;
  3730.           endAnimation = true;
  3731.         }
  3732.       } else {
  3733.         currentBox.showcaseAnimationFrame--;
  3734.         if (currentBox.showcaseAnimationFrame <= 0) {
  3735.           currentBox.showcaseAnimationFrame = 0;
  3736.           endAnimation = true;
  3737.         }
  3738.       }
  3739.       
  3740.       var newWidth = currentBox.showcaseIdleWidth + (currentBox.showcaseActiveWidth - currentBox.showcaseIdleWidth) * currentBox.showcaseAnimationFrame / animationFrames;
  3741.       var newHeight = currentBox.showcaseIdleHeight + (currentBox.showcaseActiveHeight - currentBox.showcaseIdleHeight) * currentBox.showcaseAnimationFrame / animationFrames;
  3742.       
  3743.       if (newWidth > showcaseBox.boxObject.width) {
  3744.         // We're getting out of the limits!! Set maximum size that will fit the window...
  3745.         newHeight = ((newHeight - thumbnailBorderHeight) * (showcaseBox.boxObject.width - thumbnailBorderWidth)  / (newWidth - thumbnailBorderWidth)) + thumbnailBorderHeight;
  3746.         newWidth = showcaseBox.boxObject.width;
  3747.       }
  3748.  
  3749.       if (newHeight > showcaseBox.boxObject.height) {
  3750.         // We're getting out of the limits!! Set maximum size that will fit the window...
  3751.         newWidth = ((newWidth - thumbnailBorderWidth) * (showcaseBox.boxObject.height - thumbnailBorderHeight) / (newHeight - thumbnailBorderHeight)) + thumbnailBorderWidth;
  3752.         newHeight = showcaseBox.boxObject.height;
  3753.       }
  3754.  
  3755.       var newTop = currentBox.showcaseCenterY - newHeight / 2;
  3756.       var newLeft = currentBox.showcaseCenterX - newWidth / 2;
  3757.       var limitX = showcaseBox.boxObject.width - newWidth;
  3758.       var limitY = showcaseBox.boxObject.height - newHeight;
  3759.  
  3760.       if (newTop < 0) {
  3761.         if ((currentBox.getAttribute("top") == 0) && !currentBox.showcaseGrowing) {
  3762.           newTop = -1;
  3763.         } else {
  3764.           newTop = 0;
  3765.         }
  3766.       } else if (newTop > limitY) {
  3767.         if ((currentBox.getAttribute("top") == limitY) && !currentBox.showcaseGrowing) {
  3768.           newTop = limitY + 1;
  3769.         } else {
  3770.           newTop = limitY;
  3771.         }
  3772.       }
  3773.       if (newLeft < 0) {
  3774.         if ((currentBox.getAttribute("left") == 0) && !currentBox.showcaseGrowing) {
  3775.           newLeft = -1;
  3776.         } else {
  3777.           newLeft = 0;
  3778.         }
  3779.       } else if (newLeft > limitX) {
  3780.         if ((currentBox.getAttribute("left") == limitX) && !currentBox.showcaseGrowing) {
  3781.           newLeft = limitX + 1;
  3782.         } else {
  3783.           newLeft = limitX;
  3784.         }
  3785.       }
  3786.  
  3787.       currentBox.setAttribute("top", newTop);
  3788.       currentBox.setAttribute("left", newLeft);
  3789.  
  3790.       if (isNewLayout) {
  3791.         setCanvasSize(currentBox.showcaseCanvas, (newWidth - thumbnailBorderWidth), (newHeight - thumbnailBorderHeight));
  3792.       }
  3793.       setSize(currentBox, newWidth, newHeight);
  3794.  
  3795.       if (endAnimation) {
  3796.         removeElementAt(currentAnimations, c);
  3797.         // Check if is the end of a thumbnail growing
  3798.         if (currentBox.showcaseGrowing) {
  3799.           // Show thumbnail icons
  3800.           setCurrentIconsThumbnail(currentBox);
  3801.  
  3802.           if (currentBox.showcaseCanvas.showcasePainted) {
  3803.             var showcaseCanvasScreenBox = document.getBoxObjectFor(currentBox.showcaseCanvas);
  3804.             if ((showcaseCanvasScreenBox.width > currentBox.showcaseCanvas.width) || (showcaseCanvasScreenBox.height > currentBox.showcaseCanvas.height)) {
  3805.               currentBox.showcaseCanvas.showcasePainted = false;
  3806.               setTimeout(paintThumbnail, 0, currentBox.showcaseTab);
  3807.             }
  3808.           }
  3809.         }
  3810.       } else {
  3811.         c++;
  3812.       }
  3813.     }
  3814.   }
  3815.   if (!closingShowcase && thumbnailActiveAnimation) {
  3816.     var currentWaitTime = ANIMATION_INTERVAL - (new Date().getTime() - checkpointTime);
  3817.     if (currentWaitTime < 0) {
  3818.       currentWaitTime = 0;
  3819.     }
  3820.  
  3821.     setTimeout(animationThread, currentWaitTime);
  3822.   }
  3823. }
  3824.  
  3825. function updateThumbnail(targetThumbnail, thumbWidth, thumbHeight, idleFactor, activeFactor) {
  3826. try {
  3827.   var canvasActiveW, canvasActiveH;
  3828.   var canvasIdleW, canvasIdleH;
  3829.   var windowW, windowH;
  3830.   var innerThumbWidth = thumbWidth - thumbnailBorderWidth;
  3831.   var innerThumbHeight = thumbHeight - thumbnailBorderHeight;
  3832.  
  3833.   if (targetThumbnail.showcaseImage) {
  3834.     var img = targetThumbnail.targetTab.contentDocument.imageRequest.decoderObserver;
  3835.     windowW = img.width;
  3836.     windowH = img.height;
  3837.     if ((windowW < 1) || (windowH < 1)) {
  3838.       windowW = 100;
  3839.       windowH = 100;
  3840.     }
  3841.   } else {
  3842.     windowW = targetThumbnail.targetTab.contentWindow.innerWidth;
  3843.     windowH = targetThumbnail.targetTab.contentWindow.innerHeight;
  3844.   }
  3845.   
  3846.   if (inZoomMode && !zoomFitsScreen) {
  3847.     if (windowW < innerThumbWidth) {
  3848.       canvasIdleW = windowW;
  3849.     } else {
  3850.       canvasIdleW = innerThumbWidth;
  3851.     }
  3852.     if (windowH < innerThumbHeight) {
  3853.       canvasIdleH = windowH;
  3854.     } else {
  3855.       canvasIdleH = innerThumbHeight;
  3856.     }
  3857.     canvasActiveW = canvasIdleW;
  3858.     canvasActiveH = canvasIdleH;
  3859.     zoomCurrentWidth = canvasIdleW;
  3860.     zoomCurrentHeight = canvasIdleH;
  3861.     zoomTotalWidth = windowW;
  3862.     zoomTotalHeight = windowH;
  3863.   } else {
  3864.     if ((innerThumbWidth * windowH / windowW) > innerThumbHeight) {
  3865.       canvasIdleW = Math.ceil(innerThumbHeight * windowW * idleFactor / windowH);
  3866.       canvasIdleH = Math.ceil(innerThumbHeight * idleFactor);
  3867.       canvasActiveW = Math.ceil(innerThumbHeight * windowW * activeFactor / windowH);
  3868.       canvasActiveH = Math.ceil(innerThumbHeight * activeFactor);
  3869.     } else {
  3870.       canvasIdleW = Math.ceil(innerThumbWidth * idleFactor);
  3871.       canvasIdleH = Math.ceil(innerThumbWidth * windowH * idleFactor / windowW);
  3872.       canvasActiveW = Math.ceil(innerThumbWidth * activeFactor);
  3873.       canvasActiveH = Math.ceil(innerThumbWidth * windowH * activeFactor / windowW);
  3874.     }
  3875.  
  3876.     if (targetThumbnail.showcaseImage && !imageThumbnailUpscale) {
  3877.       var img = targetThumbnail.targetTab.contentDocument.imageRequest.decoderObserver;
  3878.       if ((img.width > 0) && (img.height > 0) && ((canvasIdleW > img.width) || (canvasIdleH > img.height))) {
  3879.         canvasIdleW = img.width;
  3880.         canvasIdleH = img.height;
  3881.         canvasActiveW = canvasIdleW;
  3882.         canvasActiveH = canvasIdleH;
  3883.       }
  3884.     }
  3885.   }
  3886.  
  3887.   targetThumbnail.showcaseCanvasBox.showcaseIdleWidth = canvasIdleW + thumbnailBorderWidth;
  3888.   targetThumbnail.showcaseCanvasBox.showcaseIdleHeight = canvasIdleH + thumbnailBorderHeight;
  3889.   targetThumbnail.showcaseCanvasBox.showcaseActiveWidth = canvasActiveW + thumbnailBorderWidth;
  3890.   targetThumbnail.showcaseCanvasBox.showcaseActiveHeight = canvasActiveH + thumbnailBorderHeight;
  3891.  
  3892.   if (isNewLayout) {
  3893.     setCanvasSize(targetThumbnail.showcaseCanvas, (targetThumbnail.showcaseCanvasBox.showcaseIdleWidth - thumbnailBorderWidth), (targetThumbnail.showcaseCanvasBox.showcaseIdleHeight - thumbnailBorderHeight));
  3894.   }
  3895.  
  3896.   setSize(targetThumbnail.showcaseCanvasBox, 
  3897.     targetThumbnail.showcaseCanvasBox.showcaseIdleWidth, 
  3898.     targetThumbnail.showcaseCanvasBox.showcaseIdleHeight);
  3899. } catch (e) {
  3900.   // Probably we failed because the thumbnail has disappeared, so fail silently
  3901. }
  3902. }
  3903.  
  3904. function updateThumbnails(thumbWidth, thumbHeight, idleFactor, activeFactor) {
  3905.   var targetItem;
  3906.  
  3907.   var pendingSelectedThumbnailIndex = 0;
  3908.  
  3909.   if (inZoomMode) {
  3910.     targetItem = zoomTargetThumbnail;
  3911.     if ((targetItem) && (targetItem.showcaseCanvas) && (targetItem.showcaseCanvasBox)) {
  3912.       try {
  3913.         updateThumbnail(targetItem, thumbWidth, thumbHeight, 1, 1);
  3914.       } catch (e) {
  3915.         alert("updateThumbs1: " + e);
  3916.       }
  3917.  
  3918.       if (!targetItem.showcaseCanvasBox.hasAttribute("top")) {
  3919.         targetItem.showcaseCanvasBox.setAttribute("top", 0);
  3920.         targetItem.showcaseCanvasBox.setAttribute("left", 0);
  3921.       }
  3922.  
  3923.       var showcaseCanvasScreenBox = document.getBoxObjectFor(targetItem.showcaseCanvas);
  3924.       if (!targetItem.showcaseCanvas.showcasePainted || (showcaseCanvasScreenBox.width > targetItem.showcaseCanvas.width) || (showcaseCanvasScreenBox.height > targetItem.showcaseCanvas.height)) {
  3925. //      if (!targetItem.showcaseCanvas.showcasePainted || (targetItem.showcaseCanvasBox.showcaseIdleWidth > targetItem.showcaseCanvas.width) || (targetItem.showcaseCanvasBox.showcaseIdleHeight > targetItem.showcaseCanvas.height)) {
  3926.         try {
  3927.           createTooltip(targetItem);
  3928.         } catch (e) {
  3929.         // We can fail while creating the tooltip, since window 
  3930.         }
  3931.         // We're gonna paint it, so set it to false
  3932.         targetItem.showcaseCanvas.showcasePainted = false;
  3933.  
  3934.         if (paintThumbnailsAfterLoading) {
  3935.           // If it's a window's selected thumbnail, give it priority over the others
  3936.           if (pendingThumbnails.indexOf(targetItem) < 0) {
  3937.             pendingThumbnails.unshift(targetItem);
  3938.           }
  3939.         } else {
  3940.           setTimeout(paintThumbnail, 0, targetItem);
  3941.         }
  3942.       }
  3943.     }
  3944.   } else {
  3945.     for (var i = 0; i < processedWindows.length; i++) {
  3946.       var targetWindow = processedWindows[i];
  3947.       if (targetWindow.processedTabs) {
  3948.         var tabbrowser = targetWindow.targetWindow.getBrowser();
  3949.         var currentSelectedTab = tabbrowser.getBrowserForTab(tabbrowser.mCurrentTab);
  3950.  
  3951.         for (var j = 0; j< targetWindow.processedTabs.length; j++) {
  3952.           // Resize canvas and canvasBox
  3953.           targetItem = targetWindow.processedTabs[j];
  3954.         
  3955.           if ((targetItem) && (targetItem.showcaseCanvas) && (targetItem.showcaseCanvasBox)) {
  3956.             try {
  3957.               updateThumbnail(targetItem, thumbWidth, thumbHeight, idleFactor, activeFactor);
  3958.             } catch (e) {
  3959.               alert("updateThumbs1: " + e);
  3960.             }
  3961.  
  3962.             if (!targetItem.showcaseCanvasBox.hasAttribute("top")) {
  3963.               targetItem.showcaseCanvasBox.setAttribute("top", 0);
  3964.               targetItem.showcaseCanvasBox.setAttribute("left", 0);
  3965.             }
  3966.  
  3967.             var showcaseCanvasScreenBox = document.getBoxObjectFor(targetItem.showcaseCanvas);
  3968.             if (!targetItem.showcaseCanvas.showcasePainted || (showcaseCanvasScreenBox.width > targetItem.showcaseCanvas.width) || (showcaseCanvasScreenBox.height > targetItem.showcaseCanvas.height) || (renderingType == 2)) {
  3969. //              if (!targetItem.showcaseCanvas.showcasePainted || (targetItem.showcaseCanvasBox.showcaseIdleWidth > targetItem.showcaseCanvas.width) || (targetItem.showcaseCanvasBox.showcaseIdleHeight > targetItem.showcaseCanvas.height) || (renderingType == 2)) {
  3970.               try {
  3971.                 createTooltip(targetItem);
  3972.               } catch (e) {
  3973.                 // We can fail while creating the tooltip, since window 
  3974.               }
  3975.               // We're gonna paint it, so set it to false
  3976.               targetItem.showcaseCanvas.showcasePainted = false;
  3977.               if (paintThumbnailsAfterLoading) {
  3978.                 // If it's a window's selected thumbnail, give it priority over the others
  3979.                 if (pendingThumbnails.indexOf(targetItem) < 0) {
  3980.                   if (paintSelectedTabsFirst && (targetItem.targetTab == currentSelectedTab)) {
  3981.                     insertElementAt(pendingThumbnails, targetItem, pendingSelectedThumbnailIndex);
  3982.                     pendingSelectedThumbnailIndex++;
  3983.                   } else {
  3984.                     pendingThumbnails.push(targetItem);
  3985.                   }
  3986.                 }
  3987.               } else {
  3988.                 setTimeout(paintThumbnail, 0, targetItem);
  3989.               }
  3990.             }
  3991.           }
  3992.         }
  3993.       }
  3994.     }
  3995.   }
  3996.  
  3997.   if (paintThumbnailsAfterLoading && !paintThumbnailsThread) {
  3998.     setTimeout(paintThumbnails, 0);
  3999.   }
  4000. }
  4001.  
  4002. function paintThumbnails() {
  4003.   if (pendingThumbnails.length > 0) {
  4004.     paintThumbnailsThread = true;
  4005.     var targetItem = pendingThumbnails.shift();
  4006.     paintThumbnail(targetItem);
  4007.     setTimeout(paintThumbnails, 0);
  4008.   } else {
  4009.     paintThumbnailsThread = false;
  4010.   }
  4011. }
  4012.  
  4013. function paintThumbnail(targetThumbnail) {
  4014.   try {
  4015.   if (targetThumbnail.showcaseCanvasBox.hidden)
  4016.     return;
  4017.  
  4018.   if (targetThumbnail.showcaseCanvas && targetThumbnail.showcaseCanvas.showcasePainted)
  4019.     return;
  4020.  
  4021.   var currentWebBrowserPrint = targetThumbnail.targetTab.contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
  4022.                    .getInterface(Components.interfaces.nsIWebBrowserPrint);
  4023.  
  4024.   if (currentWebBrowserPrint.doingPrint || currentWebBrowserPrint.doingPrintPreview) return;
  4025.  
  4026.   var ctx = targetThumbnail.showcaseCanvas.getContext("2d");
  4027.   var showcaseCanvasBox = document.getBoxObjectFor(targetThumbnail.showcaseCanvas);
  4028.   var targetWidth = showcaseCanvasBox.width;
  4029.   var targetHeight = showcaseCanvasBox.height;
  4030.   
  4031.   targetThumbnail.showcaseCanvas.width = targetWidth;
  4032.   targetThumbnail.showcaseCanvas.height = targetHeight;
  4033.  
  4034.   if (targetThumbnail.showcaseImage) {
  4035.     var img = targetThumbnail.targetTab.contentDocument.imageRequest.decoderObserver;
  4036.     ctx.drawImage(img, 0, 0, targetWidth, targetHeight);    
  4037.   } else if (!targetThumbnail.showcaseIETab && !targetThumbnail.showcaseBlank && !targetThumbnail.showcaseEmbedded) {
  4038.     if (inZoomMode && !zoomFitsScreen) {
  4039.       ctx.save();
  4040.  
  4041.       ctx.drawWindow(targetThumbnail.targetTab.contentWindow, 
  4042.         targetThumbnail.targetTab.contentWindow.scrollX + zoomOffsetX, 
  4043.         targetThumbnail.targetTab.contentWindow.scrollY + zoomOffsetY, 
  4044.         zoomCurrentWidth, 
  4045.         zoomCurrentHeight, 
  4046.         "rgb(255,255,255)");
  4047.       ctx.restore();
  4048.     } else if (renderingType == 0) {
  4049.       ctx.save();
  4050.       ctx.scale(targetWidth/targetThumbnail.targetTab.contentWindow.innerWidth, targetHeight/targetThumbnail.targetTab.contentWindow.innerHeight);
  4051.  
  4052.       ctx.drawWindow(targetThumbnail.targetTab.contentWindow, 
  4053.         targetThumbnail.targetTab.contentWindow.scrollX, 
  4054.         targetThumbnail.targetTab.contentWindow.scrollY, 
  4055.         targetThumbnail.targetTab.contentWindow.innerWidth, 
  4056.         targetThumbnail.targetTab.contentWindow.innerHeight, 
  4057.         "rgb(255,255,255)");
  4058.       ctx.restore();
  4059.     } else if (renderingType == 1) {
  4060.       ctx.save();
  4061.       ctx.scale(targetWidth/targetThumbnail.targetTab.contentWindow.innerWidth, targetHeight/targetThumbnail.targetTab.contentWindow.innerHeight);
  4062.  
  4063.       // bug 313178: when painting thumbnails without scroll, there's an important bug
  4064.       ctx.drawWindow(targetThumbnail.targetTab.contentWindow, 
  4065.         0, 
  4066.         0, 
  4067.         targetThumbnail.targetTab.contentWindow.innerWidth, 
  4068.         targetThumbnail.targetTab.contentWindow.innerHeight + targetThumbnail.targetTab.contentWindow.scrollMaxY, 
  4069.         "rgb(255,255,255)");
  4070.       ctx.restore();
  4071.     } else if (renderingType == 2) {
  4072.       // bug 313178: when painting thumbnails without scroll, there's an important bug
  4073.       ctx.drawWindow(targetThumbnail.targetTab.contentWindow, 
  4074.         0, 
  4075.         0, 
  4076.         targetWidth, 
  4077.         targetHeight + targetThumbnail.targetTab.contentWindow.scrollMaxY, 
  4078.         "rgb(255,255,255)");
  4079.     } else if (renderingType == 3) {
  4080.       if (intermediateCache == null) {
  4081.         intermediateCache = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
  4082.       }
  4083.       
  4084.       intermediateCache.width = targetThumbnail.targetTab.contentWindow.innerWidth;
  4085.       intermediateCache.height = targetThumbnail.targetTab.contentWindow.innerHeight;
  4086.       var intermediateCacheContext = intermediateCache.getContext("2d");
  4087.       intermediateCacheContext.save();
  4088.       intermediateCacheContext.drawWindow(targetThumbnail.targetTab.contentWindow, 
  4089.         targetThumbnail.targetTab.contentWindow.scrollX, 
  4090.         targetThumbnail.targetTab.contentWindow.scrollY, 
  4091.         targetThumbnail.targetTab.contentWindow.innerWidth, 
  4092.         targetThumbnail.targetTab.contentWindow.innerHeight, 
  4093.         "rgb(255,255,255)");
  4094.       intermediateCacheContext.restore();
  4095.       
  4096.       ctx.save();
  4097.       ctx.drawImage(intermediateCache, 0, 0, targetThumbnail.targetTab.contentWindow.innerWidth, targetThumbnail.targetTab.contentWindow.innerHeight, 0, 0, targetWidth, targetHeight);
  4098.       ctx.restore();
  4099.       
  4100.     }
  4101.   } else {
  4102.     ctx.clearRect(0, 0, targetWidth, targetHeight);
  4103.   }
  4104.  
  4105.   } catch (e) {
  4106.     //Paint thumbnail failed, probably because the thumbnail disappeared. Fail silently.
  4107.   }
  4108.  
  4109.   // Mark it has been painted
  4110.   if (targetThumbnail.showcaseCanvas) {
  4111.     targetThumbnail.showcaseCanvas.showcasePainted = true;
  4112.  
  4113.     // Painting is a slow process, so we check if thumbnail has changed size while we were painting
  4114.     if ((targetWidth != showcaseCanvasBox.width) || (targetHeight != showcaseCanvasBox.height)) {
  4115.       // repaint
  4116.       setTimeout(paintThumbnail, 0, targetThumbnail);
  4117.     }
  4118.   }
  4119. }
  4120.  
  4121. function updateTitle() {
  4122.   if (closingShowcase)
  4123.     return;
  4124.  
  4125.   if (!showcaseOriginalTitle) {
  4126.     if (window != window.top) {
  4127.       // Sidebar
  4128.     if (globalMode) {
  4129.         showcaseOriginalTitle = topWindow.document.getElementById(SHOWCASE_SIDEBAR).getAttribute('label');
  4130.       } else {
  4131.         showcaseOriginalTitle = topWindow.document.getElementById(SHOWCASETHISWINDOW_SIDEBAR).getAttribute('label');
  4132.       }
  4133.     } else {
  4134.       showcaseOriginalTitle = document.title;
  4135.     }
  4136.   }
  4137.  
  4138.   var finalTitle = showcaseOriginalTitle;
  4139.   var currentTitle;
  4140.  
  4141.   if (window != window.top) {
  4142.     // Sidebar
  4143.     if (topWindow.MultiSidebar) {
  4144.       if (originalGlobalMode) {
  4145.         currentTitle = topWindow.MultiSidebar.getSidebarTitle(SHOWCASE_SIDEBAR);
  4146.       } else {
  4147.         currentTitle = topWindow.MultiSidebar.getSidebarTitle(SHOWCASETHISWINDOW_SIDEBAR);
  4148.       }
  4149.     } else {
  4150.       currentTitle = topWindow.document.getElementById('sidebar-title').getAttribute('value');
  4151.     }
  4152.   } else {
  4153.     currentTitle = document.title;
  4154.   }
  4155.  
  4156.   if (showOnlyCurrent) {
  4157.     if (!showOnlyCurrentLabel) {
  4158.       var showcaseBundle = document.getElementById("bundle_showcase");
  4159.       showOnlyCurrentLabel = showcaseBundle.getString("onlyCurrentTitle");
  4160.     }
  4161.     finalTitle += " " + showOnlyCurrentLabel;
  4162.   }
  4163.  
  4164.   if (showTitleStats) {
  4165.     finalTitle += " [";
  4166.  
  4167.     if (globalMode) {
  4168.       if (processedWindows) {
  4169.         var totalTabs = 0;
  4170.         for (var c=0; c<processedWindows.length; c++) {
  4171.           if (processedWindows[c].processedTabs) {
  4172.             totalTabs += processedWindows[c].processedTabs.length;
  4173.           }
  4174.         }
  4175.         finalTitle += totalTabs;
  4176.         finalTitle += "/";
  4177.         finalTitle += processedWindows.length;
  4178.       } else {
  4179.         finalTitle += "?";
  4180.       }
  4181.     } else {
  4182.       if (processedWindows && (processedWindows.length > 0) && (processedWindows[0].processedTabs)) {
  4183.         finalTitle += processedWindows[0].processedTabs.length;
  4184.       } else {
  4185.         finalTitle += "?";
  4186.       }
  4187.     }
  4188.  
  4189.     finalTitle += "]";
  4190.   }
  4191.  
  4192.   if (currentTitle != finalTitle) {
  4193.     if (window != window.top) {
  4194.       // Sidebar
  4195.       if (topWindow.MultiSidebar) {
  4196.         if (originalGlobalMode) {
  4197.           topWindow.MultiSidebar.setSidebarTitle(SHOWCASE_SIDEBAR, finalTitle);
  4198.         } else {
  4199.           topWindow.MultiSidebar.setSidebarTitle(SHOWCASETHISWINDOW_SIDEBAR, finalTitle);
  4200.         }
  4201.       } else {
  4202.         topWindow.document.getElementById('sidebar-title').setAttribute('value', finalTitle);
  4203.       }
  4204.     } else {
  4205.       document.title = finalTitle;
  4206.     }
  4207.   }
  4208. }
  4209.  
  4210. function createTooltip(targetItem) {
  4211.   var targetTitle = targetItem.tabHeader.label;
  4212.  
  4213.   var targetURL = "";
  4214.   if (targetItem.targetTab.currentURI) {
  4215.     if (targetItem.showcaseIETab) {
  4216.       try {
  4217.         targetURL = targetItem.targetTab.contentDocument.URL.substring(IETAB_URL.length);
  4218.       } catch (stringException) {
  4219.         targetURL = targetItem.targetTab.currentURI.spec;
  4220.       }
  4221.     } else {
  4222.       targetURL = targetItem.targetTab.currentURI.spec;
  4223.     }
  4224.   }
  4225.   if (targetURL == "") targetURL = "about:blank";
  4226.  
  4227.   targetItem.showcaseCanvasSubBox.thumbnailTooltipTitle = targetTitle;
  4228.   targetItem.showcaseCanvasSubBox.thumbnailTooltipURL = targetURL;
  4229. }
  4230.  
  4231. function showingThumbnailTooltip(event) {
  4232.   event.stopPropagation();
  4233.  
  4234.   var currentTitle = document.getElementById("thumbnailTooltipTitle");
  4235.   var currentURL = document.getElementById("thumbnailTooltipURL");
  4236.   var showTooltip = false;
  4237.  
  4238.   var targetNode = document.tooltipNode;
  4239.   if (targetNode.childNodes.length == 0) {
  4240.     targetNode = targetNode.parentNode;
  4241.   }
  4242.  
  4243.   if (thumbnailTooltipTitle && targetNode.thumbnailTooltipTitle) {
  4244.     currentTitle.removeAttribute("hidden");
  4245.     currentTitle.value = targetNode.thumbnailTooltipTitle;
  4246.     showTooltip = true;
  4247.   } else {
  4248.     currentTitle.setAttribute("hidden", true);
  4249.   }
  4250.  
  4251.   if (thumbnailTooltipURL && targetNode.thumbnailTooltipURL) {
  4252.     currentURL.removeAttribute("hidden");
  4253.     currentURL.value = targetNode.thumbnailTooltipURL;
  4254.     showTooltip = true;
  4255.   } else {
  4256.     currentURL.setAttribute("hidden", true);
  4257.   }
  4258.   return showTooltip;
  4259. }
  4260.  
  4261. function mosaicRefresh() {
  4262.   var thumbWidth = mosaicWidth / mosaicColumns;
  4263.   var thumbHeight = mosaicHeight / mosaicRows;
  4264.   var currentRow = 0;
  4265.   var currentColumn = 0;
  4266.   var c = 0;
  4267.   
  4268.   if (inZoomMode) {
  4269.     for (var i = 0; i < processedWindows.length; i++) {
  4270.       var targetWindow =  processedWindows[i];
  4271.       for (var j = 0; j<targetWindow.processedTabs.length; j++) {
  4272.         var targetTab = targetWindow.processedTabs[j];
  4273.         if (targetTab.showcaseCanvasBox) {
  4274.           // We just center them
  4275.           var yPosition = mosaicHeight / 2;
  4276.           var xPosition = mosaicWidth / 2;
  4277.           var topPosition = yPosition - targetTab.showcaseCanvasBox.height / 2;
  4278.           var leftPosition = xPosition - targetTab.showcaseCanvasBox.width / 2;
  4279.           targetTab.showcaseCanvasBox.setAttribute("top", topPosition);
  4280.           targetTab.showcaseCanvasBox.setAttribute("left", leftPosition);
  4281.           targetTab.showcaseCanvasBox.showcaseCenterX = xPosition;
  4282.           targetTab.showcaseCanvasBox.showcaseCenterY = yPosition;
  4283.  
  4284.           if (targetTab == zoomTargetThumbnail) {
  4285.             // Relocate the cursors...
  4286.             var targetBoxObject = document.getBoxObjectFor(targetTab.showcaseCanvas);
  4287.             var targetX = targetBoxObject.x - showcaseBox.boxObject.x;
  4288.             var targetY = targetBoxObject.y - showcaseBox.boxObject.y;
  4289.             var cursorUp = document.getElementById("cursor-up");
  4290.             cursorUp.setAttribute("top", targetY);
  4291.             cursorUp.setAttribute("left", targetX + targetBoxObject.width / 2 - 8);
  4292.             var cursorDown = document.getElementById("cursor-down");
  4293.             cursorDown.setAttribute("top", targetY + targetBoxObject.height - 19);
  4294.             cursorDown.setAttribute("left", targetX + targetBoxObject.width / 2 - 8);
  4295.             var cursorLeft = document.getElementById("cursor-left");
  4296.             cursorLeft.setAttribute("top", targetY + targetBoxObject.height / 2 - 8);
  4297.             cursorLeft.setAttribute("left", targetX + 1);
  4298.             var cursorRight = document.getElementById("cursor-right");
  4299.             cursorRight.setAttribute("top", targetY + targetBoxObject.height / 2 - 8);
  4300.             cursorRight.setAttribute("left", targetX + targetBoxObject.width - 17);
  4301.           }
  4302.         }
  4303.       }
  4304.     }
  4305.   } else {
  4306.     for (var i = 0; i < processedWindows.length; i++) {
  4307.       var targetWindow =  processedWindows[i];
  4308.       for (var j = 0; j<targetWindow.processedTabs.length; j++) {
  4309.         var targetTab = targetWindow.processedTabs[j];
  4310.  
  4311.         if (!targetTab.showcaseCanvasBox.hidden) {
  4312.           var yPosition = currentRow * thumbHeight + thumbHeight / 2;
  4313.           var xPosition = currentColumn * thumbWidth + thumbWidth / 2;
  4314.           var topPosition = yPosition - targetTab.showcaseCanvasBox.height / 2;
  4315.           var leftPosition = xPosition - targetTab.showcaseCanvasBox.width / 2;
  4316.           targetTab.showcaseCanvasBox.setAttribute("top", topPosition);
  4317.           targetTab.showcaseCanvasBox.setAttribute("left", leftPosition);
  4318.  
  4319.           targetTab.showcaseCanvasBox.showcaseCenterX = xPosition;
  4320.           targetTab.showcaseCanvasBox.showcaseCenterY = yPosition;
  4321.           targetTab.showcaseColumn = currentColumn;
  4322.           targetTab.showcaseRow = currentRow;
  4323.  
  4324.           currentColumn++;
  4325.           if (currentColumn >= mosaicColumns) {
  4326.             currentColumn = 0;
  4327.             currentRow++;
  4328.           }
  4329.         }
  4330.       }
  4331.     }
  4332.   }
  4333. }
  4334.  
  4335. function mosaicCalculateBestGrid(width, height) {
  4336.   var retValues = new Array(2);
  4337.   var numberRows, numberColumns;
  4338.   var currentWidth;
  4339.   var numTabs = 0;
  4340.   var maxTabWidth = -1;
  4341.   var maxTabHeight = -1;
  4342.   numberRows = 1;
  4343.   var maxWidth;
  4344.   
  4345.   for (var i=0; i<processedWindows.length; i++) {
  4346.     var targetWindow = processedWindows[i];
  4347.     for (var j=0; j<targetWindow.processedTabs.length; j++) {
  4348.       if (!targetWindow.processedTabs[j].showcaseCanvasBox.hidden) {
  4349.         numTabs++;
  4350.       }
  4351.     }
  4352. // TODO: use fast way when not searching?
  4353. //    numTabs += targetWindow.processedTabs.length;
  4354.  
  4355.     if (targetWindow.showcaseLastGoodWidth > maxTabWidth) {
  4356.       maxTabWidth = targetWindow.showcaseLastGoodWidth;
  4357.     }
  4358.     if (targetWindow.showcaseLastGoodHeight > maxTabHeight) {
  4359.       maxTabHeight = targetWindow.showcaseLastGoodHeight;
  4360.     }
  4361.   }
  4362.  
  4363.   var firstIteration = true;
  4364.  
  4365.   do {
  4366.     numberColumns = Math.floor(numTabs / numberRows);
  4367.     if ((numTabs % numberRows) > 0) {
  4368.       numberColumns++;
  4369.     }
  4370.     currentWidth = width / numberColumns - thumbnailBorderWidth;
  4371.     var thumbHeight = height / numberRows - thumbnailBorderHeight;
  4372.     var widthForHeight = thumbHeight * maxTabWidth / maxTabHeight;
  4373.  
  4374.     if (currentWidth > widthForHeight) {
  4375.       currentWidth = widthForHeight;
  4376.     }
  4377.  
  4378.     if (firstIteration || (currentWidth > maxWidth)) {
  4379.       retValues[0] = numberRows;
  4380.       retValues[1] = numberColumns;
  4381.       maxWidth = currentWidth;
  4382.       firstIteration = false;
  4383.     }
  4384.     numberRows++;
  4385.   } while (currentWidth >= maxWidth);
  4386.  
  4387.   // Return information for proportions
  4388.   retValues[2] = maxTabWidth;
  4389.   retValues[3] = maxTabHeight;
  4390.   retValues[4] = numTabs;
  4391.  
  4392.   return retValues;
  4393. }
  4394.  
  4395. // getTargetWindows
  4396. // Retrieves the target windows we want to "showcase"
  4397. function getTargetWindows() {
  4398.   var windowArray = new Array();
  4399.   if (globalMode) {
  4400.     // Target all windows
  4401.     var wm = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator);
  4402.     var windowIter;
  4403.     var windowIndex = 0;
  4404.     
  4405.     if (useWindowZOrder) {
  4406.       windowIter = wm.getZOrderDOMWindowEnumerator('navigator:browser', true);
  4407.     } else {
  4408.       windowIter = wm.getEnumerator('navigator:browser');
  4409.     }
  4410.     
  4411.     while (windowIter.hasMoreElements()) {
  4412.       windowArray[windowIndex] = windowIter.getNext();
  4413.       windowIndex++;
  4414.     }
  4415.     
  4416.     if ((windowIndex == 0) && useWindowZOrder) {
  4417.       // No windows?! Verify that with getEnumerator!
  4418.       windowIter = wm.getEnumerator('navigator:browser');
  4419.     
  4420.       while (windowIter.hasMoreElements()) {
  4421.         windowArray[windowIndex] = windowIter.getNext();
  4422.         windowIndex++;
  4423.       }
  4424.     }
  4425.   } else {
  4426.     // Target "this" window (which is an argument)
  4427.     windowArray[0] = getParentWindow();
  4428.   }
  4429.  
  4430.   return windowArray;
  4431. }
  4432.  
  4433. function getParentWindow() {
  4434.   if (localTargetWindow) {
  4435.     return localTargetWindow;
  4436.   } else if (window.opener) {
  4437.     return window.opener;
  4438.   } else {
  4439.     return QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebNavigation).QueryInterface(Components.interfaces.nsIDocShellTreeItem).rootTreeItem.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow);
  4440.   }
  4441. }
  4442.  
  4443. function updateLoadingState(targetProgressTab) {
  4444.   if (targetProgressTab.showcaseProgressListener.progressListener.isLoading) {
  4445.     if (isNewLayout) {
  4446.       targetProgressTab.showcaseCanvasBox.setAttribute("loading", "newtrue");
  4447.     } else {
  4448.       targetProgressTab.showcaseCanvasBox.setAttribute("loading", "true");
  4449.     }
  4450.   } else {
  4451.     targetProgressTab.showcaseCanvasBox.setAttribute("loading", "false");
  4452.   }
  4453.  
  4454.   if (currentIconsThumbnail && (currentIconsThumbnail.showcaseTab == targetProgressTab)) {
  4455.     checkThumbnailIconsState();
  4456.   }
  4457. }
  4458.  
  4459. function updateIEState(targetProgressTab) {
  4460.   targetProgressTab.showcaseCanvasBox.setAttribute("ietab", targetProgressTab.showcaseIETab);
  4461. }
  4462.  
  4463. function updateBlankState(targetProgressTab) {
  4464.   targetProgressTab.showcaseCanvasBox.setAttribute("blank", targetProgressTab.showcaseBlank);
  4465. }
  4466.  
  4467. function setEmbeddingState(targetProgressTab, newState, repaintThumbnail) {
  4468.   targetProgressTab.showcaseEmbedded = newState;
  4469.  
  4470.   if (newState) {
  4471.     if ((targetProgressTab.targetTab.contentDocument.contentType == 'video/quicktime') || (targetProgressTab.targetTab.contentDocument.contentType == 'video/x-quicktime')) {
  4472.       targetProgressTab.showcaseCanvasBox.setAttribute("plugintype", "quicktime");
  4473.     } else if (targetProgressTab.targetTab.contentDocument.contentType == "application/x-shockwave-flash") {
  4474.       targetProgressTab.showcaseCanvasBox.setAttribute("plugintype", "flash");
  4475.     } else if (targetProgressTab.targetTab.contentDocument.contentType == "application/pdf") {
  4476.       targetProgressTab.showcaseCanvasBox.setAttribute("plugintype", "pdf");
  4477.     } else {
  4478.       targetProgressTab.showcaseCanvasBox.setAttribute("plugintype", "generic");
  4479.     }
  4480.   } else {
  4481.     targetProgressTab.showcaseCanvasBox.removeAttribute("plugintype");
  4482.   }
  4483.  
  4484.   if (repaintThumbnail) {
  4485.     setTimeout(paintThumbnail, 0, targetProgressTab);
  4486.   }
  4487. }
  4488.  
  4489. function setImageState(targetProgressTab, newState) {
  4490.   targetProgressTab.showcaseImage = newState;
  4491.  
  4492.   if (newState) {
  4493.     targetProgressTab.showcaseCanvasBox.setAttribute("isimage", "true");
  4494.   } else {
  4495.     targetProgressTab.showcaseCanvasBox.removeAttribute("isimage");
  4496.   }
  4497. }
  4498.  
  4499. function closeShowcaseTab(targetProcessedTab) {
  4500.   var tabbrowser = targetProcessedTab.targetTabWindow.targetWindow.getBrowser();
  4501.  
  4502.   if (tabbrowser.mTabContainer.childNodes.length < 2) {
  4503.     if (closeLastTabKeepOpen) {
  4504.       // Blank tab
  4505.       tabbrowser.loadURI("about:blank");
  4506.     } else {
  4507.       closeProcessedWindow(targetProcessedTab.targetTabWindow);
  4508.     }
  4509.   } else if (targetProcessedTab.showcaseCanvasBox.hasAttribute("selectedtab")) {
  4510.     var showcaseRefocus = new ShowcaseRefocus(tabbrowser, tabbrowser.tabContainer, this);
  4511.     isWaitingRefocus = true;
  4512.     tabbrowser.tabContainer.addEventListener("select", showcaseRefocus, false);
  4513.     tabbrowser.removeCurrentTab();
  4514.   } else {
  4515.     tabbrowser.removeTab(targetProcessedTab.tabHeader);
  4516.   }
  4517.   
  4518. }
  4519.  
  4520. function closeShowcaseTabs(targetProcessedTabs) {
  4521.   for (var c=0; c<processedWindows.length; c++) {
  4522.     var currentProcessedWindow = processedWindows[c];
  4523.     var selectedFound = false;
  4524.     var selectedProcessedTab = null;
  4525.     var targetTabs = new Array();
  4526.     var deleteWindow = true;
  4527.  
  4528.     for (var d=0; d<currentProcessedWindow.processedTabs.length; d++) {
  4529.       var currentProcessedTab = currentProcessedWindow.processedTabs[d];
  4530.       if (targetProcessedTabs.indexOf(currentProcessedTab) > -1) {
  4531.         if (currentProcessedTab.showcaseCanvasBox.hasAttribute("selectedtab")) {
  4532.           selectedFound = true;
  4533.           selectedProcessedTab = currentProcessedTab;
  4534.         } else {
  4535.           targetTabs.push(currentProcessedTab);
  4536.         }
  4537.       } else {
  4538.         deleteWindow = false;
  4539.       }
  4540.     }
  4541.     
  4542.     if (deleteWindow && !closeLastTabKeepOpen) {
  4543.       //currentProcessedWindow.targetWindow.close();
  4544.       currentProcessedWindow.targetWindow.setTimeout(currentProcessedWindow.targetWindow.close, 0);
  4545.     } else {
  4546.       for (var e=0; e<targetTabs.length; e++) {
  4547.         closeShowcaseTab(targetTabs[e]);
  4548.       }
  4549.       
  4550.       if (selectedFound) {
  4551.         closeShowcaseTab(selectedProcessedTab);
  4552.       }
  4553.     }
  4554.   }
  4555. }
  4556.  
  4557. // Object ShowcaseRefocus
  4558. function ShowcaseRefocus(gBrowser, targetContainer, showcaseWindow) {
  4559.   this.gBrowser = gBrowser;
  4560.   this.targetContainer = targetContainer;
  4561.   this.showcaseWindow = showcaseWindow;
  4562.   this.targetWindow = null;
  4563. }
  4564.  
  4565. ShowcaseRefocus.prototype.handleEvent = function(evt){
  4566.   if (evt.type == 'select') {
  4567.     var browserWindow = this.gBrowser.selectedBrowser.contentWindow;
  4568.     browserWindow.addEventListener("focus", this, false);
  4569.     this.targetWindow = browserWindow;
  4570.     this.targetContainer.removeEventListener("select", this, false);
  4571.   } else if (evt.type == 'focus') {
  4572.     this.targetWindow.removeEventListener("focus", this, false);
  4573.     setTimeout(this.showcaseWindow.showcaseRefocusSelf, 0);
  4574.   }
  4575. }
  4576.  
  4577. function showcaseRefocusSelf() {
  4578.   focus();
  4579.   isWaitingRefocus = false;
  4580. }
  4581.  
  4582. function closeProcessedWindow(targetProcessedWindow) {
  4583.     if ((targetProcessedWindow.targetWindow.BrowserTryToCloseWindow) && (typeof(targetProcessedWindow.targetWindow.BrowserTryToCloseWindow) == "function")) {
  4584.       targetProcessedWindow.targetWindow.BrowserTryToCloseWindow();
  4585.     } else {
  4586.       targetProcessedWindow.targetWindow.close();
  4587.     }
  4588. }
  4589.  
  4590. function closeProcessedTabContentWindow(targetProcessedTab) {
  4591.   targetProcessedTab.targetTab.contentWindow.close();
  4592. }
  4593.  
  4594. function closeProcessedTabsContentWindow(targetProcessedTabs) {
  4595.   for (var c=0; c<targetProcessedTabs.length; c++) {
  4596.     targetProcessedTabs[c].targetTab.contentWindow.close();
  4597.   }
  4598. }
  4599.  
  4600. // Object TabProgressListener
  4601. function TabProgressListener(targetProgressTab ) {
  4602.   this.targetProgressTab = targetProgressTab;
  4603.   this.isLoading = false;
  4604.   this.processedContentType = false;
  4605.   this.processedImageSize = false;
  4606.   this.progressListener = 
  4607. {
  4608.     QueryInterface: function(aIID)
  4609.     {
  4610.      if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
  4611.          aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  4612.          aIID.equals(Components.interfaces.nsISupports))
  4613.        return this;
  4614.      throw Components.results.NS_NOINTERFACE;
  4615.     },
  4616.  
  4617.     onStateChange: function(aProgress, aRequest, aStateFlags, aStatus) {
  4618.      // Update thumbnail when something happens with the browser it represents
  4619.      if ((aStateFlags & STATE_START) && (aStateFlags & STATE_IS_WINDOW)) {
  4620.        //setTimeout(checkIETab, 0, targetProgressTab);
  4621.  
  4622.        this.processedContentType = false;
  4623.  
  4624.        if (targetProgressTab.showcaseEmbedded) {
  4625.          setEmbeddingState(targetProgressTab, false, true);
  4626.        }
  4627.  
  4628.        if (targetProgressTab.showcaseImage) {
  4629.          setImageState(targetProgressTab, false);
  4630.          refreshContent();
  4631.        }
  4632.  
  4633.        if (updateThumbnailWhenContentLoaded || updateThumbnailWhenContentChanges) {
  4634.          createTooltip(targetProgressTab);
  4635.        }
  4636.      } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_WINDOW)) {
  4637.        // checkIETab(targetProgressTab);
  4638.        if (targetProgressTab.showcaseImage && !this.processedImageSize) {
  4639.          refreshContent();
  4640.        }
  4641.        if (updateThumbnailWhenContentLoaded || updateThumbnailWhenContentChanges) {
  4642.          if (targetProgressTab.showcaseCanvas.showcasePainted) {
  4643.            setTimeout(createTooltip, 0, targetProgressTab);
  4644.            targetProgressTab.showcaseCanvas.showcasePainted = false;
  4645.            setTimeout(paintThumbnail, 0, targetProgressTab);
  4646.          }
  4647.        }
  4648.      } else if ((aStateFlags & STATE_TRANSFERRING) && (aStateFlags & STATE_IS_DOCUMENT)) {
  4649.        // Process targetProgressTab.targetTab.contentDocument.contentType
  4650.        if (targetProgressTab.targetTab.contentDocument && targetProgressTab.targetTab.contentDocument.contentType && !this.processedContentType) {
  4651.          checkEmbedding(targetProgressTab, true);
  4652.          checkImage(targetProgressTab, true);
  4653.          this.processedContentType = true;
  4654.          if (targetProgressTab.showcaseImage) {
  4655.            this.processedImageSize = checkImageSize(targetProgressTab);
  4656.          }
  4657.        } else if (targetProgressTab.showcaseImage && !this.processedImageSize) {
  4658.          this.processedImageSize = checkImageSize(targetProgressTab);
  4659.        }
  4660.      }
  4661.  
  4662.      
  4663.      if (this.isLoading &&
  4664.               (!limitContentChangeUpdates || !targetProgressTab.showcaseTransferringLastUpdated || (targetProgressTab.showcaseTransferringLastUpdated < (new Date()).valueOf()))
  4665.        ) {
  4666.        if (targetProgressTab.showcaseCanvas.showcasePainted) {
  4667.          targetProgressTab.showcaseCanvas.showcasePainted = false;
  4668.          setTimeout(paintThumbnail, 0, targetProgressTab);
  4669.        }
  4670.        setTimeout(createTooltip, 0, targetProgressTab);
  4671.        targetProgressTab.showcaseTransferringLastUpdated = (new Date()).valueOf() + limitContentChangeUpdatesTime;
  4672.      }
  4673.  
  4674.      return 0;
  4675.     },
  4676.  
  4677.     onLocationChange: function(aProgress, aRequest, aURI)
  4678.     {
  4679.      // This fires when the location bar changes i.e load event is confirmed
  4680.      // or when the user switches tabs
  4681.      checkIETab(targetProgressTab, aURI.spec);
  4682.      checkBlank(targetProgressTab, aURI.spec);
  4683.  
  4684.      return 0;
  4685.     },
  4686.  
  4687.     // For definitions of the remaining functions see XulPlanet.com
  4688.     onProgressChange: function() {return 0;},
  4689.     onStatusChange: function() {return 0;},
  4690.     onSecurityChange: function() {return 0;},
  4691.     onLinkIconAvailable: function(icon) { return 0;}
  4692.   }
  4693.   
  4694.   this.targetProgressTab.targetTab.addProgressListener(this.progressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
  4695. }
  4696.  
  4697. TabProgressListener.prototype.unloadListener = function(){
  4698.   try {
  4699.     this.targetProgressTab.targetTab.removeProgressListener(this.progressListener);
  4700.   } catch (e) {}
  4701. }
  4702.  
  4703. function checkIETab(targetProgressTab, aURL) {
  4704.   if (!detectIETab) return;
  4705.  
  4706.   var currentIETabState = (aURL.toString().substr(0, IETAB_URL.length) == IETAB_URL);
  4707.   if (currentIETabState != targetProgressTab.showcaseIETab) {
  4708.     targetProgressTab.showcaseIETab = currentIETabState;
  4709.     updateIEState(targetProgressTab);
  4710.     setTimeout(paintThumbnail, 0, targetProgressTab);
  4711.   }
  4712.   if (currentIETabState) {
  4713.     setTimeout(createTooltip, 0, targetProgressTab);
  4714.   }
  4715. }
  4716.  
  4717. function checkBlank(targetProgressTab, aURL) {
  4718.   if (!detectBlank) return;
  4719.  
  4720.   var currentURL = aURL.toString();
  4721.   var currentBlankState = ((currentURL == "") || (currentURL == "about:blank"));
  4722.   if (currentBlankState != targetProgressTab.showcaseBlank) {
  4723.     targetProgressTab.showcaseBlank = currentBlankState;
  4724.     updateBlankState(targetProgressTab);
  4725.     setTimeout(paintThumbnail, 0, targetProgressTab);
  4726.   }
  4727. }
  4728.  
  4729. function checkEmbedding(targetProgressTab, repaintThumbnail) {
  4730.   if ((detectPlugin) && (targetProgressTab.targetTab.contentDocument) && (targetProgressTab.targetTab.contentDocument.embeds) && (targetProgressTab.targetTab.contentDocument.embeds.length > 0) && (targetProgressTab.targetTab.contentDocument.contentType != CONTENTTYPE_HTML) && (targetProgressTab.targetTab.contentDocument.contentType != CONTENTTYPE_XHTML) && (targetProgressTab.targetTab.contentDocument.contentType != CONTENTTYPE_XUL)) {
  4731.     // Update embedding
  4732.     setEmbeddingState(targetProgressTab, true, repaintThumbnail);
  4733.   }
  4734. }
  4735.  
  4736. function checkImage(targetProgressTab) {
  4737.   if (!detectImage) return;
  4738.   if ((targetProgressTab.targetTab.contentDocument) && (targetProgressTab.targetTab.contentDocument instanceof ImageDocument)) {
  4739.     setImageState(targetProgressTab, true);
  4740.   } else {
  4741.     setImageState(targetProgressTab, false);
  4742.   }
  4743. }
  4744.  
  4745. function checkImageSize(targetProgressTab) {
  4746.   if ((targetProgressTab.targetTab.contentDocument.imageRequest.width > 0) && (targetProgressTab.targetTab.contentDocument.imageRequest.height > 0)) {
  4747.     refreshContent();
  4748.     return true;
  4749.   }
  4750.   return false;
  4751. }
  4752.  
  4753. // Object TabEventListener
  4754. function TabEventListener(targetTab, targetWindow, showcaseWindow) {
  4755.   this.listenTab = targetTab;
  4756.   this.tabwindow = targetWindow;
  4757.   this.showcaseWindow = showcaseWindow
  4758. }
  4759.  
  4760. TabEventListener.prototype.QueryInterface = function(aIID) {
  4761.   if (aIID.equals(Components.interfaces.nsITimerCallback) ||
  4762.       aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  4763.       aIID.equals(Components.interfaces.nsISupports))
  4764.     return this;
  4765.   throw Components.results.NS_NOINTERFACE;
  4766. }
  4767.  
  4768. TabEventListener.prototype.handleEvent = function(evt){
  4769.   switch(evt.type){
  4770.     case 'resize': 
  4771.       // Update size
  4772.       try {
  4773.         this.tabwindow.showcaseLastGoodWidth = this.listenTab.targetTab.contentWindow.innerWidth;
  4774.         this.tabwindow.showcaseLastGoodHeight = this.listenTab.targetTab.contentWindow.innerHeight;
  4775.       } catch (e) {
  4776.         alert("tablisten1: " + e);
  4777.       }
  4778.       
  4779.       this.listenTab.showcaseCanvasBox.showcaseCanvas.showcasePainted = false;
  4780.       setTimeout(this.showcaseWindow.refreshContent, 0);
  4781.       break;
  4782.     case 'DOMAttrModified':
  4783.       var attrName = evt.attrName;
  4784.       switch (attrName) {
  4785.         case "busy":
  4786.           var isBusy;
  4787.           if (evt.attrChange == evt.REMOVAL) {
  4788.             isBusy = false;
  4789.           } else {
  4790.             isBusy = (evt.newValue == "true");
  4791.           }
  4792.           if (isBusy != this.listenTab.showcaseProgressListener.progressListener.isLoading) {
  4793.             this.listenTab.showcaseProgressListener.progressListener.isLoading = isBusy;
  4794.             this.showcaseWindow.updateLoadingState(this.listenTab);
  4795.           }
  4796.           break;
  4797.         case "label":
  4798.           if (evt.attrChange == evt.REMOVAL) {
  4799.             this.listenTab.showcaseCanvasBox.showcaseLabel.removeAttribute("value");
  4800.             this.listenTab.showcaseCanvasBox.showcaseLabel.removeAttribute("tooltiptext");
  4801.             this.listenTab.showcaseCanvasBox.showcaseImageLabel.removeAttribute("tooltiptext");
  4802.           } else {
  4803.             this.listenTab.showcaseCanvasBox.showcaseLabel.setAttribute("value", evt.newValue);
  4804.             this.listenTab.showcaseCanvasBox.showcaseLabel.setAttribute("tooltiptext", evt.newValue);
  4805.             this.listenTab.showcaseCanvasBox.showcaseImageLabel.setAttribute("tooltiptext", evt.newValue);
  4806.           }
  4807.           if (updateThumbnailWhenTitleChanges) {
  4808.             if (this.listenTab.showcaseCanvasBox.showcaseCanvas.showcasePainted) {
  4809.               this.listenTab.showcaseCanvasBox.showcaseCanvas.showcasePainted = false;
  4810.               setTimeout(this.showcaseWindow.paintThumbnail, 0, this.listenTab);
  4811.             }
  4812.           }
  4813.           break;
  4814.         case "image":
  4815.           if (evt.attrChange == evt.REMOVAL) {
  4816.             this.listenTab.showcaseCanvasBox.showcaseImageLabel.removeAttribute("src");
  4817.           } else {
  4818.             this.listenTab.showcaseCanvasBox.showcaseImageLabel.setAttribute("src", evt.newValue);
  4819.           }
  4820.           break;
  4821.         case "crop":
  4822.           if (evt.attrChange == evt.REMOVAL) {
  4823.             this.listenTab.showcaseCanvasBox.showcaseLabel.removeAttribute("crop");
  4824.           } else {
  4825.             this.listenTab.showcaseCanvasBox.showcaseLabel.setAttribute("crop", evt.newValue);
  4826.           }
  4827.           break;
  4828.       }
  4829.       break;
  4830.     case 'load':
  4831.       // repaint thumbnail
  4832.       this.listenTab.showcaseCanvasBox.showcaseCanvas.showcasePainted = false;
  4833.       setTimeout(this.showcaseWindow.paintThumbnail, 0, this.listenTab);
  4834.       break;
  4835.     case 'scroll':
  4836.       // set timer
  4837.       if ((this.showcaseWindow.inZoomMode) && (this.showcaseWindow.zoomTargetThumbnail == this.listenTab)) {
  4838.         this.listenTab.showcaseCanvasBox.showcaseCanvas.showcasePainted = false;
  4839.         this.showcaseWindow.checkScrollCursorsVisibility();
  4840.         setTimeout(this.showcaseWindow.paintThumbnail, 0, this.listenTab);
  4841.       } else {
  4842.         if (!this.listenTab._scrollTimer) {
  4843.           this.listenTab._scrollTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
  4844.         }
  4845.         this.listenTab._scrollTimer.cancel();
  4846.         this.listenTab._scrollTimer.initWithCallback(this, 200, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
  4847.       }
  4848.       break;
  4849.  
  4850. //    case 'select':
  4851. //    case 'close':
  4852. //    case 'unload':
  4853. //      checkTabClosed(this.listenTab, this.tabbrowser);
  4854. //      setTimeout(checkTabClosed, 0, this.listenTab, this.tabwindow);
  4855. //      break;
  4856.   }
  4857. }
  4858.  
  4859. TabEventListener.prototype.notify = function(timer) {
  4860.   // repaint thumbnail
  4861.   this.listenTab.showcaseCanvasBox.showcaseCanvas.showcasePainted = false;
  4862.   setTimeout(this.showcaseWindow.paintThumbnail, 0, this.listenTab);
  4863. }
  4864.  
  4865. /*
  4866. function resizeTab(targetTab) {
  4867.   updateThumbnail(targetTab, thumbWidth, thumbHeight, thumbnailIdleSizeFactor / 100, thumbnailActiveSizeFactor / 100);
  4868.   if (targetTab.showcaseCanvas.showcasePainted) {
  4869.     targetTab.showcaseCanvas.showcasePainted = false;
  4870.     paintThumbnail(targetTab);
  4871.   }
  4872.  
  4873.   mosaicRefresh();
  4874. }
  4875. */
  4876.  
  4877. // Object TabsChangeListener
  4878. function TabsChangeListener(targetWindow, showcaseWindow) {
  4879.   this.targetWindow = targetWindow;
  4880.   this.showcaseWindow = showcaseWindow;
  4881. }
  4882.  
  4883. TabsChangeListener.prototype.handleEvent = function(evt){
  4884.   switch(evt.type){
  4885.     case 'DOMNodeInserted':
  4886.       setTimeout(this.showcaseWindow.checkTabCreation, 0, this.targetWindow, 15);
  4887.       break;
  4888.     case 'DOMNodeRemoved':
  4889.       setTimeout(this.showcaseWindow.checkTabDestruction, 0, this.targetWindow);
  4890.       break;
  4891.     case 'select':
  4892.       setTimeout(this.showcaseWindow.updateBorders, 0, this.targetWindow);
  4893.       if (this.showcaseWindow.showOnlyCurrent) {
  4894.         setTimeout(this.showcaseWindow.refreshContent, 0, this.targetWindow);
  4895.       }
  4896.       
  4897.       if (this.showcaseWindow.synchFindBar) {
  4898.         checkSynchFindBar(this.targetWindow.targetWindow, this.showcaseWindow);
  4899.       }
  4900.       
  4901.       setTimeout(this.showcaseWindow.ensureSelectedThumbnailVisible, 0, this.targetWindow);
  4902.       break;
  4903.   }
  4904.  
  4905. //  checkTabCreation(this.targetWindow);
  4906. }
  4907.  
  4908. function checkSynchFindBar(targetWindow, showcaseWindow) {
  4909.   // check if we're showcase tab
  4910.   if (targetWindow == showcaseWindow.topWindow) {
  4911.     if (showcaseWindow.top != showcaseWindow.topWindow) {
  4912.       // Check if this showcase tab has been selected
  4913.       var browser = targetWindow.getBrowser().selectedBrowser.contentWindow;
  4914.       if (browser.wrappedJSObject) {
  4915.         browser = browser.wrappedJSObject;
  4916.       }
  4917.       if (browser == showcaseWindow) {
  4918.         var findToolbar = targetWindow.document.getElementById("FindToolbar");
  4919.         if (!findToolbar.hidden) {
  4920.           if (targetWindow.closeFindBar) {
  4921.             targetWindow.closeFindBar();
  4922.           } else if (targetWindow.gFindBar) {
  4923.             if (targetWindow.gFindBar.closeFindBar) {
  4924.               targetWindow.gFindBar.closeFindBar();
  4925.             } else {
  4926.               targetWindow.gFindBar.close();
  4927.             }
  4928.           }
  4929.           setTimeout(toggleFind, 0);
  4930.         }
  4931.       } else if (showcaseWindow.searchActive) {
  4932.         if (browser.isShowcaseWindow) {
  4933.           browser.toggleFind();
  4934.         } else if (targetWindow.openFindBar) {
  4935.           targetWindow.openFindBar();
  4936.         } else if (targetWindow.gFindBar) {
  4937.           if (targetWindow.gFindBar.openFindBar) {
  4938.             targetWindow.gFindBar.openFindBar();
  4939.           } else {
  4940.             targetWindow.gFindBar.open();
  4941.           }
  4942.         }
  4943.         showcaseWindow.toggleFind();
  4944.       }
  4945.     }
  4946.   }
  4947. }
  4948.  
  4949.  
  4950. function getProcessedTabForTab(targetTab, targetWindow) {
  4951.   var foundProcessedTab = null;
  4952.  
  4953.   for (var c=0; (c<targetWindow.processedTabs.length)&&!foundProcessedTab; c++) {
  4954.     if (targetWindow.processedTabs[c].targetTab == targetTab) {
  4955.       foundProcessedTab = targetWindow.processedTabs[c];
  4956.     }
  4957.   }
  4958.  
  4959.   return foundProcessedTab;
  4960. }
  4961.  
  4962. function checkTabCreation(targetProcessedWindow, attempts) {
  4963.   try {
  4964.   var found = false;
  4965.   var tabbrowser = targetProcessedWindow.targetWindow.getBrowser();
  4966.   var totalTabs = tabbrowser.tabContainer.childNodes.length;
  4967.   var tabsReordered = false;
  4968.   var currentProcessedIndex = 0;
  4969.   var orderedProcessedTabs = new Array();
  4970.  
  4971.   for (var j = 0; j< totalTabs; j++) {
  4972.     var currentTab = tabbrowser.tabContainer.childNodes.item(j);
  4973.     var targetTab = tabbrowser.getBrowserForTab(currentTab);
  4974.  
  4975.     if (targetTab.contentWindow && (!targetTab.contentWindow.isShowcaseWindow && (!targetTab.contentWindow.wrappedJSObject || !targetTab.contentWindow.wrappedJSObject.isShowcaseWindow))) {
  4976.       var currentProcessedTab = getProcessedTabForTab(targetTab, targetProcessedWindow);
  4977.       if (!currentProcessedTab) {
  4978.         var currentProcessedTab = new ProcessedTab(targetTab);
  4979.  
  4980.         // link new tab
  4981.         var newThumbnail = createThumbnail(currentTab, currentProcessedTab, tabbrowser, targetProcessedWindow);
  4982.  
  4983.         // insert in document
  4984.         showcaseBox.insertBefore(newThumbnail, selectionBox);
  4985.  
  4986.         // Set border, just in case this creation doesn't triggers a "select" event
  4987.         // (like "open link in tab"?)
  4988.         updateTabBorder(currentProcessedTab , targetProcessedWindow);
  4989.  
  4990.         targetProcessedWindow.processedTabs.push(currentProcessedTab);
  4991.         orderedProcessedTabs.push(currentProcessedTab);
  4992.  
  4993.         found = true;
  4994.         if (j < (totalTabs - 1)) {
  4995.           tabsReordered = true;
  4996.         }
  4997.       } else {
  4998.         orderedProcessedTabs.push(currentProcessedTab);
  4999.         if (!tabsReordered) {
  5000.           if (targetProcessedWindow.processedTabs[currentProcessedIndex].targetTab != targetTab) {
  5001.             tabsReordered = true;
  5002.           }
  5003.           currentProcessedIndex++;
  5004.         }
  5005.       }
  5006.     }
  5007.   }
  5008.  
  5009.   //Were tabs reordered?
  5010.   if (tabsReordered) {
  5011.     // Reset the listener
  5012.     if (orderedProcessedTabs.length > 1) {
  5013.       var foundProcessedTab = false;
  5014.       for (var c=0; (c<(orderedProcessedTabs.length-1)) && !foundProcessedTab; c++) {
  5015.         if (targetProcessedWindow.processedTabs[c] != orderedProcessedTabs[c]) {
  5016.           if (orderedProcessedTabs[c+1] == targetProcessedWindow.processedTabs[c]) {
  5017.             orderedProcessedTabs[c].tabHeader.removeEventListener("DOMAttrModified", orderedProcessedTabs[c].showcaseTabEventListener, false);
  5018.             orderedProcessedTabs[c].tabHeader.addEventListener("DOMAttrModified", orderedProcessedTabs[c].showcaseTabEventListener, false);
  5019.             foundProcessedTab = true;
  5020.           }
  5021.           if (orderedProcessedTabs[c] == targetProcessedWindow.processedTabs[c+1]) {
  5022.             targetProcessedWindow.processedTabs[c].tabHeader.removeEventListener("DOMAttrModified", targetProcessedWindow.processedTabs[c].showcaseTabEventListener, false);
  5023.             targetProcessedWindow.processedTabs[c].tabHeader.addEventListener("DOMAttrModified", targetProcessedWindow.processedTabs[c].showcaseTabEventListener, false);
  5024.             foundProcessedTab = true;
  5025.           }
  5026.         }
  5027.       }
  5028.     }
  5029.     targetProcessedWindow.processedTabs = orderedProcessedTabs;
  5030.     found = true;
  5031.   }
  5032.  
  5033.   if (found) {
  5034.     updateTitle();
  5035.     refreshContent();
  5036.   }
  5037.   } catch (e) {
  5038.     if (attempts > 0) {
  5039.       setTimeout(checkTabCreation, 10, --attempts);
  5040.     } else {
  5041.       alert("checkTabCreation - " + e);
  5042.     }
  5043.   }
  5044. }
  5045.  
  5046. function checkTabDestruction(targetProcessedWindow) {
  5047.   try {
  5048.   var found = false;
  5049.   var tabbrowser = targetProcessedWindow.targetWindow.getBrowser();
  5050.   var tabArray = new Array();
  5051.  
  5052.   for (var j = 0; j< tabbrowser.tabContainer.childNodes.length; j++) {
  5053.     tabArray[j] = tabbrowser.getBrowserForTab(tabbrowser.tabContainer.childNodes.item(j));
  5054.   }
  5055.   var tabArrayArgument = new DualArgument(tabArray, targetProcessedWindow);
  5056.  
  5057.   if (targetProcessedWindow.processedTabs.some(singleTabDestructionCheck, tabArrayArgument)) {
  5058.     updateTitle();
  5059.     setTimeout(refreshContent, 0);
  5060.   }
  5061.  
  5062.   } catch (e) { alert("checkTabDestruction - " + e); }
  5063. }
  5064.  
  5065. // Helper function that will check if an element is inside another
  5066. function singleTabDestructionCheck(element, index, array) {
  5067.   if ((this.firstArgument.indexOf(element.targetTab) == -1) && element.showcaseCanvasBox) {
  5068.     // Destruction found
  5069.     showcaseBox.removeChild(element.showcaseCanvasBox);
  5070.     unlinkProcessedTab(element, this.secondArgument);
  5071.     return true;
  5072.   }
  5073.  
  5074.   return false;
  5075. }
  5076.  
  5077. // Helper object that simply holds an argument
  5078. function DualArgument(firstArgument, secondArgument) {
  5079.   this.firstArgument = firstArgument;
  5080.   this.secondArgument = secondArgument;
  5081. }
  5082.  
  5083. function showShowcaseOptions() {
  5084.   
  5085.   var features;
  5086.   try {
  5087.     var prefs = Components.classes["@mozilla.org/preferences-service;1"]
  5088.                           .getService(Components.interfaces.nsIPrefBranch);
  5089.     var instantApply = prefs.getBoolPref("browser.preferences.instantApply");
  5090.     features = "chrome,titlebar,toolbar,centerscreen," + (instantApply ? "dialog=no" : "modal,resizable");
  5091.   } catch (e) {
  5092.     features = "chrome,titlebar,toolbar,centerscreen,modal,resizable";
  5093.   }
  5094.   openDialog(OPTIONS_URL, "", features);
  5095. }
  5096.  
  5097. // Object ProcessedWindow
  5098. function ProcessedWindow(targetWindow) {
  5099.   this.targetWindow = targetWindow;
  5100.   this.processedTabs = new Array();
  5101. }
  5102.  
  5103. // Object ProcessedTab
  5104. function ProcessedTab(targetTab) {
  5105.   this.targetTab = targetTab;
  5106. }
  5107.  
  5108. // Search functions
  5109. function updateFind() {
  5110.   if (inZoomMode) {
  5111.     return;
  5112.   }
  5113.  
  5114.   var field = document.getElementById("find-field");
  5115.   var statusIcon = document.getElementById("find-status-icon");
  5116.   var statusText = document.getElementById("find-status");
  5117.   var invertField = document.getElementById("find-invert");
  5118.  
  5119.   var targetWindow;
  5120.   var targetProcessedTab;
  5121.   var noMatchingTabs = true;
  5122.  
  5123.   var value = field.value;
  5124.   var invert = invertField.getAttribute("checked");
  5125.  
  5126.   if (!searchActive || (value.length < 1)) {
  5127.     invertField.setAttribute("disabled", true);
  5128.  
  5129.     if (showOnlyCurrent) {
  5130.       updateShowOnlyCurrent();
  5131.     } else {
  5132.       for (var c=0; (c<processedWindows.length); c++) {
  5133.         targetWindow = processedWindows[c];
  5134.         for (var d=0; (d<targetWindow.processedTabs.length); d++) {
  5135.           targetProcessedTab = targetWindow.processedTabs[d];
  5136.           targetProcessedTab.showcaseCanvasBox.hidden = false;
  5137.         }
  5138.       }
  5139.     }
  5140.  
  5141.     noMatchingTabs = false;
  5142.   } else {
  5143.     invertField.setAttribute("disabled", false);
  5144.  
  5145.     var moreSpecificSearch = false;
  5146.     var lessSpecificSearch = false;
  5147.     // Check if we've just to update
  5148.     if ((!lastSearchCaseSensitive && searchCaseSensitive) ||
  5149.         ((lastSearchFindType == FINDTYPE_ANY) && (searchFindType != FINDTYPE_ANY)) ||
  5150.         ((value.indexOf(lastSearch) == 0) && (value.length > lastSearch.length))) {
  5151.       moreSpecificSearch = true;
  5152.     }
  5153.     if ((lastSearchCaseSensitive && !searchCaseSensitive) ||
  5154.         ((lastSearchFindType != FINDTYPE_ANY) && (searchFindType == FINDTYPE_ANY)) ||
  5155.         ((lastSearch.indexOf(value) == 0) && (lastSearch.length > value.length))) {
  5156.       lessSpecificSearch = true;
  5157.     }
  5158.  
  5159.     gFinder.caseSensitive = searchCaseSensitive;
  5160.  
  5161.     for (var c=0; (c<processedWindows.length); c++) {
  5162.       targetWindow = processedWindows[c];
  5163.  
  5164.       if (showOnlyCurrent) {
  5165.         var tabbrowser = targetWindow.targetWindow.getBrowser();
  5166.         var tabs = tabbrowser.mTabContainer.childNodes;
  5167.         var selectedTab = tabbrowser.getBrowserForTab(tabs[tabbrowser.mTabContainer.selectedIndex]);
  5168.  
  5169.         for (var j = 0; j<targetWindow.processedTabs.length; j++) {
  5170.           var targetProcessedTab = targetWindow.processedTabs[j];
  5171.           if (targetProcessedTab.targetTab == selectedTab) {
  5172.             if ((!moreSpecificSearch || !(targetProcessedTab.showcaseCanvasBox.hidden == invert)) ||
  5173.                 (!lessSpecificSearch || !(targetProcessedTab.showcaseCanvasBox.hidden != invert))) {
  5174.               var res = checkTabFind(targetProcessedTab.targetTab, value);
  5175.   
  5176.               if ((res && !invert) || (!res && invert)) {
  5177.                 noMatchingTabs = false;
  5178.                 targetProcessedTab.showcaseCanvasBox.hidden = false;
  5179.               } else {
  5180.                 targetProcessedTab.showcaseCanvasBox.hidden = true;
  5181.               }
  5182.             } else if (!targetProcessedTab.showcaseCanvasBox.hidden) {
  5183.               noMatchingTabs = false;
  5184.             }
  5185.           } else {
  5186.             targetProcessedTab.showcaseCanvasBox.hidden = true;
  5187.           }
  5188.         }
  5189.       } else {
  5190.         for (var d=0; (d<targetWindow.processedTabs.length); d++) {
  5191.           targetProcessedTab = targetWindow.processedTabs[d];
  5192.  
  5193.           if ((!moreSpecificSearch || (targetProcessedTab.showcaseCanvasBox.hidden == invert)) &&
  5194.               (!lessSpecificSearch || (targetProcessedTab.showcaseCanvasBox.hidden != invert))) {
  5195.             var res = checkTabFind(targetProcessedTab.targetTab, value);
  5196.   
  5197.             if ((res && !invert) || (!res && invert)) {
  5198.               noMatchingTabs = false;
  5199.               targetProcessedTab.showcaseCanvasBox.hidden = false;
  5200.             } else {
  5201.               targetProcessedTab.showcaseCanvasBox.hidden = true;
  5202.             }
  5203.           } else if (!targetProcessedTab.showcaseCanvasBox.hidden) {
  5204.             noMatchingTabs = false;
  5205.           }
  5206.         }
  5207.       }
  5208.     }
  5209.   }
  5210.  
  5211.   if (noMatchingTabs) {
  5212.     // We couldn't find any tabs. Show this to the user,and show ALL the tabs
  5213.     statusIcon.setAttribute("status", "notfound");
  5214.  
  5215.     if (!findPhraseNotFoundLabel) {
  5216.       var showcaseBundle = document.getElementById("bundle_showcase");
  5217.       findPhraseNotFoundLabel = showcaseBundle.getString("findPhraseNotFound");
  5218.     }
  5219.  
  5220.     if (window.sidebarFindBar) {
  5221.       statusIcon.setAttribute("hidden", false);
  5222.       statusIcon.setAttribute("tooltiptext", findPhraseNotFoundLabel);
  5223.     } else {
  5224.       statusText.value = findPhraseNotFoundLabel;
  5225.     }
  5226.     field.setAttribute("status", "notfound");      
  5227.     
  5228.     if (showOnlyCurrent) {
  5229.       updateShowOnlyCurrent();
  5230.     } else {
  5231.       // Show all the thumbnails
  5232.       for (var c=0; (c<processedWindows.length); c++) {
  5233.         targetWindow = processedWindows[c];
  5234.         for (var d=0; (d<targetWindow.processedTabs.length); d++) {
  5235.           targetWindow.processedTabs[d].showcaseCanvasBox.hidden = false;
  5236.         }
  5237.       }
  5238.     }
  5239.   } else {
  5240.     // Remove status
  5241.     statusIcon.removeAttribute("status");
  5242.     if (window.sidebarFindBar) {
  5243.       statusIcon.setAttribute("hidden", true);
  5244.       statusIcon.removeAttribute("tooltiptext");
  5245.     } else {
  5246.       statusText.value = "";
  5247.     }
  5248.     field.removeAttribute("status");
  5249.  
  5250.     // Save last correct search parameters
  5251.     lastSearchCaseSensitive = searchCaseSensitive;
  5252.     lastSearchFindType = searchFindType;
  5253.     lastSearch = value;
  5254.   }
  5255. }
  5256.  
  5257. function findTypeChanged(findType) {
  5258.   searchFindType = findType;
  5259.   refreshContent();
  5260. }
  5261.  
  5262. function checkTabFind(targetTab, value) {
  5263.   var found = false;
  5264.   
  5265.   if ((searchFindType == FINDTYPE_TITLE) || (searchFindType == FINDTYPE_ANY)) {
  5266.     if (targetTab.contentDocument && targetTab.contentDocument.title) {
  5267.       var targetTitle = targetTab.contentDocument.title;
  5268.       if (searchCaseSensitive) {
  5269.         found = (targetTitle.indexOf(value) > -1);
  5270.       } else {
  5271.         found = (targetTitle.toLowerCase().indexOf(value.toLowerCase()) > -1);
  5272.       }
  5273.     }
  5274.   }
  5275.  
  5276.   if (!found && ((searchFindType == FINDTYPE_LOCATION) || (searchFindType == FINDTYPE_ANY))) {
  5277.     if (targetTab.currentURI) {
  5278.       var targetLocation = targetTab.currentURI.spec;
  5279.       if (searchCaseSensitive) {
  5280.         found = (targetLocation.indexOf(value) > -1);
  5281.       } else {
  5282.         found = (targetLocation.toLowerCase().indexOf(value.toLowerCase()) > -1);
  5283.       }
  5284.     }
  5285.   }
  5286.  
  5287.   if (!found && ((searchFindType == FINDTYPE_CONTENT) || (searchFindType == FINDTYPE_ANY))) {
  5288.     try {
  5289.       found = findWindowContent(targetTab.contentWindow, value);
  5290.     } catch (e) {
  5291.       // Fail silently
  5292.     }
  5293.   }
  5294.  
  5295.   return found;
  5296. }
  5297.  
  5298. function findWindowContent(targetWindow, value) {
  5299.   var found;
  5300.  
  5301.   var body = targetWindow.document.body;
  5302.   var count = body.childNodes.length;
  5303.   var searchRange = targetWindow.document.createRange();
  5304.   searchRange.setStart(body, 0);
  5305.   searchRange.setEnd(body, count);
  5306.   var startPt = targetWindow.document.createRange();
  5307.   var endPt = targetWindow.document.createRange();
  5308.   startPt.setStart(body, 0);
  5309.   startPt.setEnd(body, 0);
  5310.   endPt.setStart(body, count);
  5311.   endPt.setEnd(body, count);
  5312.  
  5313.   found = gFinder.Find(value, searchRange, startPt, endPt);
  5314.  
  5315.   if (found) {
  5316.     return true;
  5317.   } else if (targetWindow.frames) {
  5318.     for (var c=0; (c<targetWindow.frames.length) && !found; c++) {
  5319.       found = findWindowContent(targetWindow.frames[c], value);
  5320.     }
  5321.   }
  5322.  
  5323.   return found;
  5324. }
  5325.  
  5326. function toggleSearchCaseSensitivity(caseSensitive) {
  5327.   this.searchCaseSensitive = caseSensitive;
  5328.   refreshContent();
  5329. }
  5330.  
  5331. function findShortcutAction() {
  5332.   if (!searchActive) {
  5333.     toggleFind();
  5334.   } else {
  5335.     selectFindBar();
  5336.     focusFindBar();
  5337.   }
  5338. }
  5339.  
  5340. function toggleFind() {
  5341.   if (window.sidebarFindBar) {
  5342.     if (findBarMode == 0) {
  5343.       selectFindBar();
  5344.       focusFindBar();
  5345.       return;
  5346.     } else if (findBarMode == 1) {
  5347.       return;
  5348.     }
  5349.   }
  5350.   var findToolbar = document.getElementById("FindToolbar");
  5351.  
  5352.   searchActive = !searchActive;
  5353.  
  5354.   findToolbar.setAttribute("hidden", !searchActive);
  5355.   if (searchActive) {
  5356.     selectFindBar();
  5357.     focusFindBar();
  5358.   } else {
  5359.     updateFind();
  5360.     showcaseBox.focus();
  5361.   }
  5362.   refreshContent();
  5363. }
  5364.  
  5365. function focusFindBar()
  5366. {
  5367.   var findField = document.getElementById("find-field");
  5368.   findField.focus();    
  5369. }
  5370.  
  5371. function selectFindBar()
  5372. {
  5373.   var findField = document.getElementById("find-field");
  5374.   findField.select();    
  5375. }
  5376.  
  5377. function onFindBarKeyPress(evt)
  5378. {
  5379.   if (evt.keyCode == KeyEvent.DOM_VK_RETURN) {
  5380.     openFoundSearchResult();
  5381.   }
  5382.   else if (evt.keyCode == KeyEvent.DOM_VK_ESCAPE) {
  5383.     toggleFind();
  5384.     evt.preventDefault();
  5385.   } 
  5386.   else if (evt.keyCode == KeyEvent.DOM_VK_PAGE_UP) {
  5387.     if (scrollBoxObject) scrollBoxObject.scrollBy(0, -scrollBoxObject.height);
  5388.     evt.preventDefault();
  5389.   }
  5390.   else if (evt.keyCode == KeyEvent.DOM_VK_PAGE_DOWN) {
  5391.     if (scrollBoxObject) scrollBoxObject.scrollBy(0, scrollBoxObject.height);
  5392.     evt.preventDefault();
  5393.   }
  5394.   else if (evt.keyCode == KeyEvent.DOM_VK_UP) {
  5395.     if (scrollBoxObject) scrollBoxObject.scrollByLine(-1);
  5396.     evt.preventDefault();
  5397.   }
  5398.   else if (evt.keyCode == KeyEvent.DOM_VK_DOWN) {
  5399.     if (scrollBoxObject) scrollBoxObject.scrollByLine(1);
  5400.     evt.preventDefault();
  5401.   }
  5402.  
  5403.  
  5404. function onFindTypeKeyPress(evt, findTypeField)
  5405. {
  5406.   if (evt.keyCode == KeyEvent.DOM_VK_RETURN) {
  5407.     openFoundSearchResult();
  5408.   }
  5409.   else if (evt.keyCode == KeyEvent.DOM_VK_ESCAPE) {
  5410.     toggleFind();
  5411.     evt.preventDefault();
  5412.   } 
  5413.   else if (evt.keyCode == KeyEvent.DOM_VK_UP) {
  5414.     if (findTypeField.selectedIndex > 0) {
  5415.       findTypeField.selectedIndex--;
  5416.     } else {
  5417.       findTypeField.selectedIndex = findTypeField.firstChild.childNodes.length - 1;
  5418.     }
  5419.     evt.preventDefault();
  5420.   }
  5421.   else if (evt.keyCode == KeyEvent.DOM_VK_DOWN) {
  5422.     if (findTypeField.selectedIndex >= (findTypeField.firstChild.childNodes.length - 1)) {
  5423.       findTypeField.selectedIndex = 0;
  5424.     } else {
  5425.       findTypeField.selectedIndex++;
  5426.     }
  5427.     evt.preventDefault();
  5428.   }
  5429.  
  5430. function openFoundSearchResult() {
  5431.   var firstVisibleFound = false;
  5432.   var firstVisibleTab = null;
  5433.   var secondVisibleFound = false;
  5434.  
  5435.   // if there's just one result, open it
  5436.   for (var c=0; (c<processedWindows.length) && !secondVisibleFound; c++) {
  5437.     var currentProcessedWindow = processedWindows[c];
  5438.     for (var d=0; (d<currentProcessedWindow.processedTabs.length) && !secondVisibleFound; d++) {
  5439.       var currentProcessedTab = currentProcessedWindow.processedTabs[d];
  5440.       if (!currentProcessedTab.showcaseCanvasBox.hidden) {
  5441.         // Is visible
  5442.         if (!firstVisibleFound) {
  5443.           firstVisibleFound = true;
  5444.           firstVisibleTab = currentProcessedTab;
  5445.         } else {
  5446.           secondVisibleFound = true;
  5447.         }
  5448.       }
  5449.     }
  5450.   }
  5451.  
  5452.   if (firstVisibleFound && !secondVisibleFound) {
  5453.     openTab(firstVisibleTab);
  5454.   }
  5455. }
  5456.  
  5457. function findTypeKeyInhibit(evt) {
  5458.   if ((evt.keyCode == KeyEvent.DOM_VK_RETURN) || (evt.keyCode == KeyEvent.DOM_VK_ESCAPE) || (evt.keyCode == KeyEvent.DOM_VK_UP) || (evt.keyCode == KeyEvent.DOM_VK_DOWN)) {
  5459.     evt.preventDefault();
  5460.   }
  5461. }
  5462.  
  5463.  
  5464. // Duplicate/Merge tabs functions
  5465.  
  5466. function moveTabsToNewWindow(closeDuplicated) {
  5467.   var currentIndex = 0, curBrowser, browsersArray = new Array();
  5468.  
  5469.   if (selectedTabs.length > 0) {
  5470.     for (var c=0; c<selectedTabs.length; c++) {
  5471.       var curBrowser = selectedTabs[c].targetTab;
  5472.       browsersArray[currentIndex] = [copyTabHistory(curBrowser.webNavigation.sessionHistory),
  5473.         curBrowser.contentWindow.scrollX, curBrowser.contentWindow.scrollY,
  5474.         curBrowser.markupDocumentViewer.textZoom,selectedTabs[c]];
  5475.       currentIndex++;
  5476.     }
  5477.   } else {
  5478.       var curBrowser = showcasePopupTab.targetTab;
  5479.       browsersArray[currentIndex] = [copyTabHistory(curBrowser.webNavigation.sessionHistory),
  5480.         curBrowser.contentWindow.scrollX, curBrowser.contentWindow.scrollY,
  5481.         curBrowser.markupDocumentViewer.textZoom,showcasePopupTab];
  5482.       currentIndex++;
  5483.   }
  5484.  
  5485.   // create new window
  5486.   isWaitingRefocus = true;
  5487.   var newWindow = processedWindows[0].targetWindow.openDialog(browserChromeURL, '_blank', 'chrome,all,dialog=no');
  5488.   
  5489.   var duplicateWindowListener = new DuplicateWindowListener(newWindow, browsersArray, closeDuplicated, this);
  5490.   newWindow.addEventListener('load', duplicateWindowListener, false);
  5491. }
  5492.  
  5493. function DuplicateWindowListener(newWindow, browsersArray, closeDuplicated, showcaseWindow) {
  5494.   this.newWindow = newWindow;
  5495.   this.browsersArray = browsersArray;
  5496.   this.closeDuplicated = closeDuplicated;
  5497.   this.showcaseWindow = showcaseWindow;
  5498. }
  5499.  
  5500. DuplicateWindowListener.prototype.handleEvent = function(evt){
  5501.   waitForSessionHistory(this.newWindow, this.browsersArray, 10, this.closeDuplicated);
  5502.   setTimeout(this.showcaseWindow.showcaseRefocusSelf, 0);
  5503.  
  5504.   // Unregister listener
  5505.   this.newWindow.removeEventListener("load", this, false);
  5506. }
  5507.  
  5508. function duplicateInNewWindow() {
  5509.   moveTabsToNewWindow(false);
  5510. }
  5511.  
  5512. function mergeInNewWindow() {
  5513.   // duplicate tabs, close the existing ones...
  5514.   moveTabsToNewWindow(true);
  5515. }
  5516.  
  5517.  
  5518. // add cloned tabs to a browser window
  5519. function setTabsInBrowser(aWindow, pages) {
  5520.   var y = 0, openedBrowser, newTab;
  5521.   var targetBrowser = aWindow.getBrowser();
  5522.  
  5523.   while (y < pages.length) {
  5524.     if (y == 0) {
  5525.       // Fill the first tab
  5526.       newTab = targetBrowser.mTabContainer.firstChild;
  5527.     } else {
  5528.       newTab = targetBrowser.addTab();
  5529.     }
  5530.     openedBrowser = targetBrowser.getBrowserForTab(newTab);
  5531.     setClonedContent(openedBrowser, pages[y]);
  5532.     y++;
  5533.   }
  5534. }
  5535.  
  5536. // sets previously cloned content into a browser (tab)
  5537. // Argument1 aBrowser: a newly created xul:browser to set the contents to
  5538. // Argument2 aClonedContents: an Array containing browser history, scrollposition and zoomfactor, to be set to the browser
  5539. function setClonedContent(aBrowser, aClonedContents) {
  5540.   if (aClonedContents[0].length == 0) return;
  5541.  
  5542.   cloneTabHistory(aBrowser.webNavigation, aClonedContents[0]);
  5543.  
  5544.   setScrollPosition(15, aBrowser, aClonedContents[1], aClonedContents[2]);
  5545.   setTextZoom(15, aBrowser, aClonedContents[3]);
  5546. }
  5547.  
  5548. function setTextZoom(attempts, newBrowser, aTextZoomValue) {
  5549.   newBrowser.markupDocumentViewer.textZoom = aTextZoomValue;
  5550.   if (attempts && (newBrowser.markupDocumentViewer.textZoom != aTextZoomValue)) {
  5551.     window.setTimeout(setTextZoom, 10,--attempts, newBrowser, aTextZoomValue);
  5552.     return;
  5553.   }
  5554. }
  5555.  
  5556. function setScrollPosition(attempts, newBrowser, aScrollValueX, aScrollValueY) {
  5557.   newBrowser.contentWindow.scrollTo(aScrollValueX, aScrollValueY);
  5558.   if (attempts && ((newBrowser.contentWindow.scrollX != aScrollValueX)||(newBrowser.contentWindow.scrollY != aScrollValueY))) {
  5559.     window.setTimeout(setScrollPosition, 10, --attempts, newBrowser, aScrollValueX, aScrollValueY);
  5560.     return;
  5561.   }
  5562. }
  5563.  
  5564. // Clone an array of history entries into a browsers webNavigation.sessionHistory
  5565. // Argument1 webNav: The webNavigation object of a newly created browser.
  5566. // Argument2 originalHistory: an array containing history entries from the original browser
  5567. function cloneTabHistory(webNav, originalHistory) {
  5568.   var newHistory = webNav.sessionHistory
  5569.  
  5570.   newHistory.QueryInterface(Components.interfaces.nsISHistoryInternal);
  5571.  
  5572.   // delete history entries if they are present
  5573.   if (newHistory.count > 0) newHistory.PurgeHistory(newHistory.count);
  5574.  
  5575.   for (var i = 0; i < originalHistory.length; i++) {
  5576.     var entry = originalHistory[i].QueryInterface(Components.interfaces.nsISHEntry);
  5577.     var newEntry = cloneHistoryEntry(entry);
  5578.     if (newEntry)
  5579.       newHistory.addEntry(newEntry, true);
  5580.   }
  5581.  
  5582.   // Goto current history location
  5583.   if (originalHistory.index < originalHistory.length) {
  5584.     try {
  5585.       webNav.gotoIndex(originalHistory.index);
  5586.     } catch(e) {
  5587.       window.setTimeout(webNav.gotoIndex, 0, originalHistory.index);
  5588.     }
  5589.   }
  5590. }
  5591.  
  5592. // copy a sessionHistory and put it into an array
  5593. // Argument1 originalHistory: webNavigation.sessionHistory browser history to be copied
  5594. // returns: an array containing a copy of the history
  5595. function copyTabHistory(originalHistory, aOnlyBack)  {
  5596.   // variables used in this function
  5597.   var backHistoryEnabled, forwardHistoryEnabled, forwardPagesNum, backPagesNum;
  5598.   var pageCount, currentPageNum, firstPageNum, lastPageNum;
  5599.  
  5600.   // check if copying forward or back history is enabled and checking for history length to be copied
  5601.   currentPageNum = originalHistory.index;
  5602.   lastPageNum = originalHistory.count-1;
  5603.  
  5604.   firstPageNum = 0;
  5605.  
  5606.   if (!aOnlyBack) {
  5607.     pageCount = lastPageNum+1;
  5608.   }
  5609.   else
  5610.     pageCount = currentPageNum+1;
  5611.  
  5612.   currentPageNum = currentPageNum-firstPageNum;
  5613.  
  5614.   var copiedHistory = new Array();
  5615.   for (var i = firstPageNum; i < pageCount; i++) {
  5616.     copiedHistory.push(originalHistory.getEntryAtIndex(i, false));
  5617.   }
  5618.   copiedHistory.index = currentPageNum;
  5619.  
  5620.   return copiedHistory;
  5621. }
  5622.  
  5623. function cloneHistoryEntry(aEntry) {
  5624.   if (!aEntry)
  5625.     return null;
  5626.   aEntry = aEntry.QueryInterface(Components.interfaces.nsISHContainer);
  5627.   var newEntry = aEntry.clone();
  5628.   newEntry = newEntry.QueryInterface(Components.interfaces.nsISHContainer);
  5629.   newEntry.loadType = Math.floor(aEntry.loadType);
  5630.   if (aEntry.childCount) {
  5631.     for (var j = 0; j < aEntry.childCount; j++) {
  5632.         var childEntry = cloneHistoryEntry(aEntry.GetChildAt(j));
  5633.         if (childEntry)
  5634.           newEntry.AddChild(childEntry, j);
  5635.     }
  5636.   }
  5637.   return newEntry;
  5638. }
  5639.  
  5640. function waitForSessionHistory(targetWindow, pages, attempts, closeDuplicated) {
  5641.   // Test if sessionHistory exists yet
  5642.   var webNav = targetWindow.getBrowser().webNavigation;
  5643.   try    {
  5644.     webNav.sessionHistory;
  5645.   } catch (err) {
  5646.     // webNav.sessionHistory is not yet available, try again later
  5647.     if (attempts) 
  5648.       window.setTimeout(waitForSessionHistory, 100, targetWindow, pages, --attempts, closeDuplicated);
  5649.  
  5650.     return;
  5651.   }
  5652.   if ((webNav.sessionHistory == null) && attempts) {
  5653.     window.setTimeout(waitForSessionHistory, 100, targetWindow, pages, --attempts, closeDuplicated);
  5654.     return;
  5655.   }
  5656.  
  5657.   var openedBrowser = targetWindow.getBrowser().mCurrentBrowser;
  5658.   setTabsInBrowser(targetWindow, pages);
  5659.  
  5660.   if (closeDuplicated) {
  5661.     var tabsArray = new Array();
  5662.     for (var c=0; c<pages.length; c++) {
  5663.       tabsArray[c] = pages[c][4];
  5664.     }
  5665.     closeShowcaseTabs(tabsArray);
  5666.   }
  5667. }
  5668.  
  5669. function selectionBoxStart(e) {
  5670.   if (e.button != 0) {
  5671.     return;
  5672.   }
  5673.  
  5674.   if (e.originalTarget != showcaseBox) {
  5675.     return;
  5676.   }
  5677.  
  5678.   if (selectionBox.hasAttribute("hidden")) {
  5679.     selectionBox.removeAttribute("hidden");
  5680.   }
  5681.  
  5682.   removeAllElements(originalSelection);
  5683.   if (!e.ctrlKey && !e.shiftKey) {
  5684.     removeAllSelections();
  5685.   } else {
  5686.     for (var c=0; c<selectedTabs.length; c++) {
  5687.       originalSelection.push(selectedTabs[c]);
  5688.     }
  5689.   }
  5690.   selectionStartX = e.layerX;
  5691.   selectionStartY = e.layerY;
  5692.   selectionEndX = e.layerX;
  5693.   selectionEndY = e.layerY;
  5694.   selectionBox.setAttribute("top", selectionStartY);
  5695.   selectionBox.setAttribute("left", selectionStartX);
  5696.   setSize(selectionBox, 0, 0);
  5697. }
  5698.  
  5699. function selectionBoxEnd(e) {
  5700.   if (e.button != 0) {
  5701.     return;
  5702.   }
  5703.   endSelection();
  5704. }
  5705.  
  5706. function endSelection() {
  5707.   if (!selectionBox.hasAttribute("hidden")) {
  5708.     selectionBox.setAttribute("hidden", true);
  5709.   }
  5710. }
  5711.  
  5712. function boxMouseOut(el) {
  5713.   if (dropBox.hasAttribute("hidden") && selectionBox.hasAttribute("hidden") && !inZoomMode) return;
  5714.  
  5715.   var hasExited = (el.relatedTarget != el.currentTarget);
  5716.   var currentNode = el.relatedTarget;
  5717.  
  5718.   if (currentNode) {
  5719.     while (hasExited && currentNode.parentNode) {
  5720.       hasExited = ((el.currentTarget != currentNode.parentNode) && (currentNode.localName != "tooltip"));
  5721.       currentNode = currentNode.parentNode;
  5722.     }
  5723.   }
  5724.  
  5725.   if (hasExited) {
  5726.     if (inZoomMode)
  5727.       leaveZoomMode();
  5728.  
  5729.     if (!selectionBox.hasAttribute("hidden"))
  5730.       endSelection();
  5731.  
  5732.     if (!dropBox.hasAttribute("hidden"))
  5733.       dropBox.setAttribute("hidden", "true");
  5734.   }
  5735. }
  5736.  
  5737. function selectionBoxCheck(e) {
  5738.   if (e.button != 0) {
  5739.     return;
  5740.   }
  5741.   if (selectionBox.hasAttribute("hidden")) {
  5742.     return;
  5743.   }
  5744.  
  5745.   var newWidth, newHeight;
  5746.   if (e.layerX < selectionStartX) {
  5747.     selectionBox.setAttribute("left", e.layerX);
  5748.     newWidth = selectionStartX - e.layerX;
  5749.   } else {
  5750.     selectionBox.setAttribute("left", selectionStartX);
  5751.     newWidth = e.layerX - selectionStartX - 1;
  5752.   }
  5753.  
  5754.   if (e.layerY < selectionStartY) {
  5755.     selectionBox.setAttribute("top", e.layerY);
  5756.     newHeight = selectionStartY - e.layerY;
  5757.   } else {
  5758.     selectionBox.setAttribute("top", selectionStartY);
  5759.     newHeight = e.layerY - selectionStartY - 1;
  5760.   }
  5761.   setSize(selectionBox, newWidth, newHeight);
  5762.  
  5763.   selectionEndX = e.layerX;
  5764.   selectionEndY = e.layerY;
  5765.  
  5766.   // Check for selection
  5767.   for (var c=0; c<processedWindows.length; c++) {
  5768.     var currentProcessedWindow = processedWindows[c];
  5769.     for (var d=0; d<currentProcessedWindow.processedTabs.length; d++) {
  5770.       var currentProcessedTab = processedWindows[c].processedTabs[d];
  5771.       if (!currentProcessedTab.showcaseCanvasBox.hidden) {
  5772.         if (checkTabInSelectionBox(currentProcessedTab)) {
  5773.           if (e.ctrlKey) {
  5774.             if (selectedTabs.indexOf(currentProcessedTab) > -1) {
  5775.               if (originalSelection.indexOf(currentProcessedTab) > -1) {
  5776.                 removeFromSelection(currentProcessedTab);
  5777.               }
  5778.             } else if (originalSelection.indexOf(currentProcessedTab) < 0) {
  5779.               addToSelection(currentProcessedTab);
  5780.             }
  5781.           } else {
  5782.             if (selectedTabs.indexOf(currentProcessedTab) < 0) {
  5783.               addToSelection(currentProcessedTab);
  5784.             }
  5785.             var originalSelectionIndex = originalSelection.indexOf(currentProcessedTab);
  5786.             if (originalSelectionIndex > -1) {
  5787.               removeElementAt(originalSelection, originalSelectionIndex);
  5788.             }
  5789.           }
  5790.         } else {
  5791.           if (e.ctrlKey) {
  5792.             if (selectedTabs.indexOf(currentProcessedTab) > -1) {
  5793.               if (originalSelection.indexOf(currentProcessedTab) < 0) {
  5794.                 removeFromSelection(currentProcessedTab);
  5795.               }
  5796.             } else if (originalSelection.indexOf(currentProcessedTab) > -1) {
  5797.               addToSelection(currentProcessedTab);
  5798.             }
  5799.           } else if ((selectedTabs.indexOf(currentProcessedTab) > -1) && (originalSelection.indexOf(currentProcessedTab) < 0)) {
  5800.             removeFromSelection(currentProcessedTab);
  5801.           }
  5802.         }
  5803.       }
  5804.     }
  5805.   }
  5806. }
  5807.  
  5808. function showcaseBoxCheckKey(el) {
  5809.   if (el.ctrlKey || el.altKey || el.metaKey) return;
  5810.  
  5811.   if (el.charCode >= 33) {
  5812.     var createdChar = String.fromCharCode(el.charCode);
  5813.  
  5814.     if ((createdChar != "+") && (createdChar != "-")) {
  5815.       var field = document.getElementById("find-field");
  5816.  
  5817.       if (!searchActive) {
  5818.         if (!window.sidebarFindBar || (findBarMode != 1)) {
  5819.           var findToolbar = document.getElementById("FindToolbar");
  5820.           searchActive = true;
  5821.           findToolbar.setAttribute("hidden", false);
  5822.         }
  5823.         field.value = createdChar;
  5824.       } else {
  5825.         field.value += createdChar;
  5826.       }
  5827.       field.inputField.focus();
  5828.       setTimeout(field.setSelectionRange, 0, field.length, field.length);
  5829.  
  5830.       refreshContent();
  5831.     }
  5832.   }
  5833. }
  5834.  
  5835. function checkTabInSelectionBox(targetTab) {
  5836.   var selectionLeft, selectionRight, selectionUp, selectionDown;
  5837.   if (selectionStartX < selectionEndX) {
  5838.     selectionLeft = selectionStartX;
  5839.     selectionRight = selectionEndX;
  5840.   } else {
  5841.     selectionRight = selectionStartX;
  5842.     selectionLeft = selectionEndX;
  5843.   }
  5844.   if (selectionStartY < selectionEndY) {
  5845.     selectionUp = selectionStartY;
  5846.     selectionDown = selectionEndY;
  5847.   } else {
  5848.     selectionUp = selectionEndY;
  5849.     selectionDown = selectionStartY;
  5850.   }
  5851.   if ((targetTab.showcaseCanvasBox.boxObject.x > selectionRight) || ((targetTab.showcaseCanvasBox.boxObject.width + targetTab.showcaseCanvasBox.boxObject.x) < selectionLeft)) {
  5852.     return false;
  5853.   }
  5854.   if ((targetTab.showcaseCanvasBox.boxObject.y > selectionDown) || ((targetTab.showcaseCanvasBox.boxObject.height + targetTab.showcaseCanvasBox.boxObject.y) < selectionUp)) {
  5855.     return false;
  5856.   }
  5857.  
  5858.   return true;
  5859. }
  5860.  
  5861. // Firefox 3.5 and newer 
  5862. var newDragDropHandler = {
  5863.   onDragStart: function(event) {
  5864.     var dt = event.dataTransfer;
  5865.  
  5866.     var currentTime = new Date().getTime();
  5867.     var tabList = "";
  5868.     var uriList = "";
  5869.     var mozUrlList = "";
  5870.     var htmlList = "<ul>\n";
  5871.     var textList = "";
  5872.     
  5873.     var targetTabs;
  5874.     if (selectedTabs.length > 1) {
  5875.       targetTabs = selectedTabs;
  5876.     } else {
  5877.       targetTabs = new Array();
  5878.       targetTabs.push(event.currentTarget.showcaseTab);
  5879.     }
  5880.     for (var c=0; c<targetTabs.length; c++) {
  5881. //      dataArray.push(createTransferDataForThumbnail(targetTabs[c], currentTime.toString() + "-" + c));
  5882.       var value;
  5883.       var tabId = currentTime.toString() + "-" + c;
  5884.       
  5885.       if (targetTabs[c].targetTab.currentURI) {
  5886.         value = targetTabs[c].targetTab.currentURI.spec;
  5887.       } else {
  5888.         value = "about:blank";
  5889.       }
  5890.     
  5891.       if ((detectIETab) && (value.substr(0, IETAB_URL.length) == IETAB_URL)) {
  5892.         value = value.substring(IETAB_URL.length);
  5893.       }
  5894.     
  5895.       if (tabList != "") {
  5896.         tabList += "\n";
  5897.         uriList += "\n";
  5898.         mozUrlList += "\n";
  5899.         textList += "\n";
  5900.       }
  5901.       mozUrlList += value + "\n" + targetTabs[c].targetTab.contentDocument.title;
  5902.       htmlList += "<li><a href=\"" + value + "\">" + targetTabs[c].targetTab.contentDocument.title + "</a></li>";
  5903.       uriList += value;
  5904.       textList += value;
  5905.       var targetTab = targetTabs[c].targetTab;
  5906.       if (targetTab.wrappedJSObject) {
  5907.         targetTab = targetTab.wrappedJSObject;
  5908.       }
  5909.       var targetTabId = tabId.toString();
  5910.       if (targetTab.showcaseTabId) {
  5911.         targetTabId = targetTab.showcaseTabId;
  5912.       } else {
  5913.         targetTab.showcaseTabId = targetTabId;
  5914.       }
  5915.       tabList += targetTabId;
  5916.     }
  5917.     dt.setData("text/x-showcase-tab", tabList);
  5918.     dt.setData("text/uri-list", uriList);
  5919.     dt.setData("text/x-moz-url", mozUrlList);
  5920.     dt.setData("text/html", htmlList);
  5921.     dt.setData("text/unicode", textList);
  5922.   },
  5923.   
  5924.   onDragOver: function(event) {
  5925.     var types = event.dataTransfer.types;
  5926.     var supportedTypes = ["text/x-showcase-tab", "text/uri-list" ];
  5927.     types = supportedTypes.filter(function(value) { return types.contains(value); });
  5928.     if (types.length) {
  5929.       event.preventDefault();
  5930.       onDragOverShowcaseBoard(event);
  5931.     } else {
  5932.       dropBox.setAttribute("hidden", true);
  5933.     }
  5934.   },
  5935.   
  5936.   onDrop: function(event) {
  5937.     try {
  5938.     dropBox.setAttribute("hidden", true);
  5939.     var moveIfPossible = (event.dataTransfer.dropEffect == "move");
  5940.     var currentMosaicCol = Math.floor(event.layerX * mosaicColumns / mosaicWidth);
  5941.     var currentMosaicRow = Math.floor(event.layerY * mosaicRows / mosaicHeight);
  5942.     var targetTab = getTabAt(currentMosaicRow, currentMosaicCol);
  5943.     currentMosaicCol = targetTab.showcaseColumn;
  5944.     currentMosaicRow = targetTab.showcaseRow;
  5945.     var atLeftSide = ((event.layerX - currentMosaicCol * mosaicWidth / mosaicColumns) < (mosaicWidth / (mosaicColumns * 2)));
  5946.     var targetTabWindow = getProcessedWindowForProcessedTab(targetTab);
  5947.     var tabbrowser = targetTabWindow.targetWindow.getBrowser();
  5948.     var processedTabsMoved = new Array();
  5949.  
  5950.     
  5951.     var insertionIndex = targetTab.tabHeader._tPos;
  5952.     
  5953.  
  5954.     var types = event.dataTransfer.types;
  5955.     var supportedTypes = ["text/x-showcase-tab", "text/uri-list" ];
  5956.     types = supportedTypes.filter(function(value) { return types.contains(value); });
  5957.     if (types.length) {
  5958.       var showcaseTabList = event.dataTransfer.getData(types[0]);
  5959.       var parts = showcaseTabList.split("\n");
  5960.       var targets = new Array();
  5961.       for (var d=0;d<parts.length;d++) {
  5962.         if ((parts[d].length > 0) && (parts[d].charAt(0) != '#')) {
  5963.           targets.push(parts[d]);
  5964.         }
  5965.       }
  5966.       if (targets.length > 0) {
  5967.         for (var d=0; d<targets.length; d++) {
  5968.           var currentProcessedTab = null;
  5969.           var currentTab = null;
  5970.           var currentTabHeader = null;
  5971.           var currentTabWindow = null;
  5972.           var urlTab = false;
  5973.           var isProcessed = true;
  5974.           if (types[0] == "text/x-showcase-tab") {
  5975.     
  5976.             // Try to find it in processed windows
  5977.             currentProcessedTab = findProcessedTabById(targets[d]);
  5978.     
  5979.             if (currentProcessedTab == null) {
  5980.               isProcessed = false;
  5981.               // Make search in all windows...
  5982.               var searchResult = findTabById(targets[d]);
  5983.               if (searchResult) {
  5984.                 currentTab = searchResult.tab;
  5985.                 currentTabHeader = searchResult.tabHeader;
  5986.                 currentTabWindow = searchResult.window;
  5987.               }
  5988.             } else {
  5989.               currentTab = currentProcessedTab.targetTab;
  5990.               currentTabHeader = currentProcessedTab.tabHeader;
  5991.               currentTabWindow = getProcessedWindowForProcessedTab(currentProcessedTab).targetWindow;
  5992.             }
  5993.           } else {
  5994.             // We're inserting a new URL if possible...
  5995.             var url = targets[d];
  5996.             
  5997.             if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
  5998.                 /^\s*(javascript|data):/.test(url))
  5999.               continue;
  6000.     
  6001.             // Insert new tab
  6002.             var newTab = tabbrowser.addTab(url);
  6003.             currentTabWindow = targetTabWindow.targetWindow;
  6004.             currentTabHeader = newTab;
  6005.             currentTab = tabbrowser.getBrowserForTab(newTab);
  6006.             urlTab = true;
  6007.           }
  6008.           
  6009.           if (currentTab != null) {
  6010.             if ((currentTabWindow == targetTabWindow.targetWindow) && (moveIfPossible || urlTab)) {
  6011.               // Just move the tab
  6012.               if (atLeftSide) {
  6013.                 
  6014.                 if ((currentTabHeader._tPos < insertionIndex) && (insertionIndex > 0)) {
  6015.                   tabbrowser.moveTabTo(currentTabHeader, insertionIndex - 1);
  6016.                 } else {
  6017.                   tabbrowser.moveTabTo(currentTabHeader, insertionIndex);
  6018.                 }
  6019.                 if (currentTabHeader._tPos >= insertionIndex) {
  6020.                   insertionIndex++;
  6021.                 }
  6022.                 
  6023.               } else {
  6024.                 
  6025.                 if (currentTabHeader._tPos >= insertionIndex) {
  6026.                   insertionIndex++;
  6027.                 }
  6028.                 tabbrowser.moveTabTo(currentTabHeader, insertionIndex);
  6029.                 
  6030.               }
  6031.             } else {
  6032.               // Insert new tab
  6033.               var newTab = tabbrowser.addTab(url);
  6034.               if (atLeftSide) {
  6035.                 
  6036.                 if ((newTab._tPos < insertionIndex) && (insertionIndex > 0)) {
  6037.                   tabbrowser.moveTabTo(newTab, insertionIndex - 1);
  6038.                 } else {
  6039.                   tabbrowser.moveTabTo(newTab, insertionIndex);
  6040.                 }
  6041.                 if (newTab._tPos >= insertionIndex) {
  6042.                   insertionIndex++;
  6043.                 }
  6044.                 
  6045.               } else {
  6046.                 
  6047.                 if (newTab._tPos >= insertionIndex) {
  6048.                   insertionIndex++;
  6049.                 }
  6050.                 tabbrowser.moveTabTo(newTab, insertionIndex);
  6051.                 
  6052.               }
  6053.     
  6054.               var pageInfo = [copyTabHistory(currentTab.webNavigation.sessionHistory),
  6055.                 currentTab.contentWindow.scrollX, currentTab.contentWindow.scrollY,
  6056.                 currentTab.markupDocumentViewer.textZoom,currentProcessedTab];
  6057.               setClonedContent(newTab.linkedBrowser, pageInfo);
  6058.     
  6059.               if (moveIfPossible) {
  6060.                 if (currentProcessedTab) {
  6061.                   processedTabsMoved.push(currentProcessedTab);
  6062.                 } else {
  6063.                   currentTab.contentWindow.close();
  6064.                 }
  6065.               }
  6066.             }
  6067.           }
  6068.         }
  6069.       }
  6070.     }
  6071.     if (processedTabsMoved.length > 0) {
  6072.       closeShowcaseTabs(processedTabsMoved);
  6073.     }
  6074.     event.preventDefault();
  6075.     } catch (e) { alert(e); }
  6076.   }
  6077. };
  6078.  
  6079. // Drag & drop
  6080. var thumbnailObserver = {
  6081.   onDragStart: function (evt,transferData,action) {
  6082.     var dataArray = new Array();
  6083.     var currentTime = new Date().getTime();
  6084.  
  6085.     if (selectedTabs.length > 1) {
  6086.       for (var c=0; c<selectedTabs.length; c++) {
  6087.         dataArray.push(createTransferDataForThumbnail(selectedTabs[c], currentTime.toString() + "-" + c));
  6088.       }
  6089.       transferData.data = new TransferDataSet(dataArray);
  6090.     } else {
  6091.       transferData.data = createTransferDataForThumbnail(evt.currentTarget.showcaseTab, currentTime.toString());
  6092.     }
  6093.   },
  6094.   
  6095.   checkOwnDrop: function (evt,session) {
  6096.     if (!session) return false;
  6097.     
  6098.     if (session.sourceNode == evt.target) {
  6099.       mouseUpCanvas(evt);
  6100.       evt.stopPropagation();
  6101.       evt.preventDefault();
  6102.       return true;
  6103.     }
  6104.     
  6105.     return false;
  6106.   }
  6107. };
  6108.  
  6109. var boardObserver = {
  6110.   getSupportedFlavours : function () {
  6111.     var flavours = new FlavourSet();
  6112.     flavours.appendFlavour("text/x-showcase-tab");
  6113.     flavours.appendFlavour("text/x-moz-url");
  6114.     flavours.appendFlavour("application/x-moz-file", "nsIFile");
  6115.     return flavours;
  6116.   },
  6117.  
  6118.   onDragOver: function (evt,flavour,session) {
  6119.     // Drop line
  6120.     if (!session.canDrop) {
  6121.       dropBox.setAttribute("hidden", true);
  6122.       return;
  6123.     }
  6124.     onDragOverShowcaseBoard(evt);
  6125.   },
  6126.  
  6127.   onDragExit: function (aEvent, aDragSession) {
  6128.     dropBox.setAttribute("hidden", true);
  6129.   },
  6130.  
  6131.   onDrop: function (evt,dropdata,session) {
  6132.     dropBox.setAttribute("hidden", true);
  6133.  
  6134.     var currentMosaicCol = Math.floor(evt.layerX * mosaicColumns / mosaicWidth);
  6135.     var currentMosaicRow = Math.floor(evt.layerY * mosaicRows / mosaicHeight);
  6136.     var targetTab = getTabAt(currentMosaicRow, currentMosaicCol);
  6137.     currentMosaicCol = targetTab.showcaseColumn;
  6138.     currentMosaicRow = targetTab.showcaseRow;
  6139.     var atLeftSide = ((evt.layerX - currentMosaicCol * mosaicWidth / mosaicColumns) < (mosaicWidth / (mosaicColumns * 2)));
  6140.     var targetTabWindow = getProcessedWindowForProcessedTab(targetTab);
  6141.     var tabbrowser = targetTabWindow.targetWindow.getBrowser();
  6142.  
  6143.  
  6144.     const kDSIID      = Components.interfaces.nsIDragService;
  6145.     const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
  6146.     var moveIfPossible = !(session.dragAction & kCopyAction);
  6147.  
  6148.     
  6149.     var insertionIndex = targetTab.tabHeader._tPos;
  6150.     
  6151.  
  6152. //try {
  6153.     var targets = getSelectionFromXferData(session);
  6154.     var processedTabsMoved = new Array();
  6155.  
  6156.     for (var d=0; d<targets.length; d++) {
  6157.       var currentProcessedTab = null;
  6158.       var currentTab = null;
  6159.       var currentTabHeader = null;
  6160.       var currentTabWindow = null;
  6161.       var urlTab = false;
  6162.       var isProcessed = true;
  6163.       if ((targets[d].type == "showcaseId") && (session.sourceDocument != null)) {
  6164.  
  6165.         // Try to find it in processed windows
  6166.         currentProcessedTab = findProcessedTabById(targets[d].value);
  6167.  
  6168.         if (currentProcessedTab == null) {
  6169.           isProcessed = false;
  6170.           // Make search in all windows...
  6171.           var searchResult = findTabById(targets[d].value);
  6172.           if (searchResult) {
  6173.             currentTab = searchResult.tab;
  6174.             currentTabHeader = searchResult.tabHeader;
  6175.             currentTabWindow = searchResult.window;
  6176.           }
  6177.         } else {
  6178.           currentTab = currentProcessedTab.targetTab;
  6179.           currentTabHeader = currentProcessedTab.tabHeader;
  6180.           currentTabWindow = getProcessedWindowForProcessedTab(currentProcessedTab).targetWindow;
  6181.         }
  6182.       } else if (targets[d].data) {
  6183.         // We're inserting a new URL if possible...
  6184.         var url = transferUtils.retrieveURLFromData(targets[d].data, targets[d].contentType);
  6185.         
  6186.         if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
  6187.             /^\s*(javascript|data):/.test(url))
  6188.           continue;
  6189.  
  6190.         // Insert new tab
  6191.         var newTab = tabbrowser.addTab(url);
  6192.         currentTabWindow = targetTabWindow.targetWindow;
  6193.         currentTabHeader = newTab;
  6194.         currentTab = tabbrowser.getBrowserForTab(newTab);
  6195.         urlTab = true;
  6196.       }
  6197.       
  6198.       if (currentTab != null) {
  6199.         if ((currentTabWindow == targetTabWindow.targetWindow) && (moveIfPossible || urlTab)) {
  6200.           // Just move the tab
  6201.           if (atLeftSide) {
  6202.             
  6203.             if ((currentTabHeader._tPos < insertionIndex) && (insertionIndex > 0)) {
  6204.               tabbrowser.moveTabTo(currentTabHeader, insertionIndex - 1);
  6205.             } else {
  6206.               tabbrowser.moveTabTo(currentTabHeader, insertionIndex);
  6207.             }
  6208.             if (currentTabHeader._tPos >= insertionIndex) {
  6209.               insertionIndex++;
  6210.             }
  6211.             
  6212.           } else {
  6213.             
  6214.             if (currentTabHeader._tPos >= insertionIndex) {
  6215.               insertionIndex++;
  6216.             }
  6217.             tabbrowser.moveTabTo(currentTabHeader, insertionIndex);
  6218.             
  6219.           }
  6220.         } else {
  6221.           // Insert new tab
  6222.           var newTab = tabbrowser.addTab(url);
  6223.           if (atLeftSide) {
  6224.             
  6225.             if ((newTab._tPos < insertionIndex) && (insertionIndex > 0)) {
  6226.               tabbrowser.moveTabTo(newTab, insertionIndex - 1);
  6227.             } else {
  6228.               tabbrowser.moveTabTo(newTab, insertionIndex);
  6229.             }
  6230.             if (newTab._tPos >= insertionIndex) {
  6231.               insertionIndex++;
  6232.             }
  6233.             
  6234.           } else {
  6235.             
  6236.             if (newTab._tPos >= insertionIndex) {
  6237.               insertionIndex++;
  6238.             }
  6239.             tabbrowser.moveTabTo(newTab, insertionIndex);
  6240.             
  6241.           }
  6242.  
  6243.           var pageInfo = [copyTabHistory(currentTab.webNavigation.sessionHistory),
  6244.             currentTab.contentWindow.scrollX, currentTab.contentWindow.scrollY,
  6245.             currentTab.markupDocumentViewer.textZoom,currentProcessedTab];
  6246.           setClonedContent(newTab.linkedBrowser, pageInfo);
  6247.  
  6248.           if (moveIfPossible) {
  6249.             if (currentProcessedTab) {
  6250.               processedTabsMoved.push(currentProcessedTab);
  6251.             } else {
  6252.               currentTab.contentWindow.close();
  6253.             }
  6254.           }
  6255.         }
  6256.       }
  6257.     }
  6258.     if (processedTabsMoved.length > 0) {
  6259.       closeShowcaseTabs(processedTabsMoved);
  6260.     }
  6261. //} catch (e) { log(e); }
  6262.   },
  6263.  
  6264.   canHandleMultipleItems: true
  6265. };
  6266.  
  6267. function onDragOverShowcaseBoard(evt) {
  6268.   dropBox.removeAttribute("hidden");
  6269.   var currentMosaicCol = Math.floor(evt.layerX * mosaicColumns / mosaicWidth);
  6270.   var currentMosaicRow = Math.floor(evt.layerY * mosaicRows / mosaicHeight);
  6271.   var targetTab = getTabAt(currentMosaicRow, currentMosaicCol);
  6272.   currentMosaicCol = targetTab.showcaseColumn;
  6273.   currentMosaicRow = targetTab.showcaseRow;
  6274.   var atLeftSide = ((evt.layerX - currentMosaicCol * mosaicWidth / mosaicColumns) < (mosaicWidth / (mosaicColumns * 2)))
  6275.   setSize(dropBox, 6, mosaicHeight / mosaicRows);
  6276.   dropBox.setAttribute("top", currentMosaicRow * mosaicHeight / mosaicRows);
  6277.   
  6278.   var isFrontier = false;
  6279.   if (atLeftSide) {
  6280.     if ((currentMosaicCol == 0) && (currentMosaicRow == 0)) {
  6281.       isFrontier = true;
  6282.     } else {
  6283.       var targetRow = currentMosaicRow;
  6284.       var targetColumn = currentMosaicCol;
  6285.       if (targetColumn > 0) {
  6286.         targetColumn--;
  6287.       } else {
  6288.         targetRow--;
  6289.         targetColumn = mosaicColumns - 1;
  6290.       }
  6291.       var prevTab = getTabAt(targetRow, targetColumn);
  6292.       if (prevTab.targetTabWindow != targetTab.targetTabWindow) {
  6293.         isFrontier = true;
  6294.       }
  6295.     }
  6296.   } else {
  6297.     var targetRow = currentMosaicRow;
  6298.     var targetColumn = currentMosaicCol;
  6299.     if (targetColumn < (mosaicColumns - 1)) {
  6300.       targetColumn++;
  6301.     } else {
  6302.       targetRow++;
  6303.       targetColumn = 0;
  6304.     }
  6305.     var nextTab = getTabAt(targetRow, targetColumn);
  6306.     if (nextTab == targetTab) {
  6307.       isFrontier = true;
  6308.     } else if (nextTab.targetTabWindow != targetTab.targetTabWindow) {
  6309.       isFrontier = true;
  6310.     }
  6311.   }
  6312.  
  6313.   if (atLeftSide && isFrontier) {
  6314.     dropBox.setAttribute("dropside", "left");
  6315.     dropBox.setAttribute("left", currentMosaicCol * mosaicWidth / mosaicColumns);
  6316.   } else if (isFrontier) {
  6317.     dropBox.setAttribute("dropside", "right");
  6318.     dropBox.setAttribute("left", (currentMosaicCol + 1) * mosaicWidth / mosaicColumns - 6);
  6319.   } else {
  6320.     dropBox.setAttribute("dropside", "middle");
  6321.     if (atLeftSide) {
  6322.       if (currentMosaicCol > 0) {
  6323.         dropBox.setAttribute("left", currentMosaicCol * mosaicWidth / mosaicColumns - 1);
  6324.       } else {
  6325.         dropBox.setAttribute("left", 0);
  6326.       }
  6327.     } else {
  6328.       if ((currentMosaicCol + 1) < mosaicColumns) {
  6329.         dropBox.setAttribute("left", (currentMosaicCol + 1) * mosaicWidth / mosaicColumns - 1);
  6330.       } else {
  6331.         dropBox.setAttribute("left", (currentMosaicCol + 1) * mosaicWidth / mosaicColumns - 2);
  6332.       }
  6333.     }
  6334.   }
  6335. }
  6336.  
  6337. function getSelectionFromXferData(aDragSession) {
  6338.     var selection    = [];
  6339.     var trans = Components.classes["@mozilla.org/widget/transferable;1"]
  6340.                           .createInstance(Components.interfaces.nsITransferable);
  6341.     if (aDragSession.sourceDocument != null) {
  6342.       trans.addDataFlavor("text/x-showcase-tab");
  6343.     }
  6344.     trans.addDataFlavor("text/x-moz-url");
  6345.     trans.addDataFlavor("text/x-moz-file");
  6346.     trans.addDataFlavor("text/unicode");
  6347.     var uri, extra, rSource, rParent, parent;
  6348.     for (var i = 0; i < aDragSession.numDropItems; ++i) {
  6349.       var bestFlavour = {}, dataObj = {}, len = {};
  6350.       aDragSession.getData(trans, i);
  6351.       trans.getAnyTransferData(bestFlavour, dataObj, len);
  6352.       dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsString);
  6353.       if (!dataObj)
  6354.         continue;
  6355.       var value = dataObj.data.substring(0, len.value);
  6356.  
  6357.       var newValue = {};
  6358.       newValue.value = value;
  6359.       switch (bestFlavour.value) {
  6360.       case "text/x-showcase-tab":
  6361.         newValue.type = "showcaseId";
  6362.         break;
  6363.       case "text/x-moz-url":
  6364.       case "text/x-moz-file":
  6365.       case "text/unicode":
  6366.         newValue.type = "url";
  6367.         newValue.contentType = bestFlavour.value;
  6368.         newValue.data = dataObj.data;
  6369.         break;
  6370.       }
  6371.       selection.push(newValue);
  6372.     }
  6373.     return selection;
  6374. }
  6375.  
  6376. function createTransferDataForThumbnail(targetProcessedTab, tabId) {
  6377.   var value;
  6378.  
  6379.   if (targetProcessedTab.targetTab.currentURI) {
  6380.     value = targetProcessedTab.targetTab.currentURI.spec;
  6381.   } else {
  6382.     value = "about:blank";
  6383.   }
  6384.  
  6385.   if ((detectIETab) && (value.substr(0, IETAB_URL.length) == IETAB_URL)) {
  6386.     value = value.substring(IETAB_URL.length);
  6387.   }
  6388.  
  6389.   var urlString = value + "\n" + targetProcessedTab.targetTab.contentDocument.title;
  6390.   var htmlString = "<a href=\"" + value + "\">" + targetProcessedTab.targetTab.contentDocument.title + "</a>";
  6391.   var targetTab = targetProcessedTab.targetTab;
  6392.   if (targetTab.wrappedJSObject) {
  6393.     targetTab = targetTab.wrappedJSObject;
  6394.   }
  6395.   var targetTabId = tabId.toString();
  6396.   if (targetTab.showcaseTabId) {
  6397.     targetTabId = targetTab.showcaseTabId;
  6398.   } else {
  6399.     targetTab.showcaseTabId = targetTabId;
  6400.   }
  6401.   var data = new TransferData();
  6402.   data.addDataForFlavour("text/x-showcase-tab", targetTabId);
  6403.   if ((value == "") || (value == "about:blank")) {
  6404.     data.addDataForFlavour("text/unicode", value);
  6405.   } else {
  6406.     data.addDataForFlavour("text/x-moz-url", urlString);
  6407.     data.addDataForFlavour("text/unicode", value);
  6408.     data.addDataForFlavour("text/html", htmlString);
  6409.   }
  6410.  
  6411.   return data;
  6412. }
  6413.  
  6414. function findProcessedTabById(targetId) {
  6415.   var foundProcessedTab = null;
  6416.  
  6417.   for (var c=0; (c<processedWindows.length)&&!foundProcessedTab; c++) {
  6418.     for (var d=0; (d<processedWindows[c].processedTabs.length)&&!foundProcessedTab; d++) {
  6419.       if (processedWindows[c].processedTabs[d].targetTab.showcaseTabId && (processedWindows[c].processedTabs[d].targetTab.showcaseTabId == targetId)) {
  6420.         foundProcessedTab = processedWindows[c].processedTabs[d];
  6421.       }
  6422.     }
  6423.   }
  6424.  
  6425.   return foundProcessedTab;
  6426. }
  6427.  
  6428. function findTabById(targetId) {
  6429.   // Target all windows
  6430.   var wm = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator);
  6431.   var windowIter;
  6432.   var result = null;
  6433.     
  6434.   windowIter = wm.getEnumerator('navigator:browser');
  6435.     
  6436.   while (windowIter.hasMoreElements() && !result) {
  6437.     var currentWindow = windowIter.getNext();
  6438.     var tabbrowser = currentWindow.getBrowser();
  6439.     var tabs = tabbrowser.mTabContainer.childNodes;
  6440.     var totalTabs = tabs.length;
  6441.  
  6442.     // search tabs
  6443.     for (var j = 0; (j< totalTabs) && !result; j++) {
  6444.       var targetTab = tabbrowser.getBrowserForTab(tabs[j]);
  6445.       if (targetTab.wrappedJSObject) targetTab = targetTab.wrappedJSObject;
  6446.       if (targetTab.showcaseTabId && (targetTab.showcaseTabId == targetId)) {
  6447.         result = {};
  6448.         result.window = currentWindow;
  6449.         result.tabHeader = tabs[j];
  6450.         result.tab = targetTab;
  6451.       }
  6452.     }
  6453.   }
  6454.  
  6455.   return result;
  6456. }
  6457.  
  6458. function getDataByContentType(transferData, targetContentType) {
  6459.   var data = null;
  6460.   for (var c=0; (c<transferData.dataList.length) && (data == null); c++) {
  6461.     if ((transferData.dataList[c].flavour) && (transferData.dataList[c].flavour.contentType == targetContentType)) {
  6462.       data = transferData.dataList[c].supports;
  6463.     }
  6464.   }
  6465.   return data;
  6466. }
  6467.  
  6468. // Thumbnail icons
  6469. function setCurrentIconsThumbnail(targetElement) {
  6470.   if (targetElement == null) {
  6471.     currentIconsThumbnail = null;
  6472.     hideThumbnailIcons();
  6473.     return;
  6474.   }
  6475.  
  6476.   var targetBox;
  6477.  
  6478.   if (targetElement.showcaseCanvas) { 
  6479.     targetBox = targetElement.showcaseCanvas.showcaseCanvasBox;
  6480.   } else {
  6481.     targetBox = targetElement.showcaseCanvasBox;
  6482.   }
  6483.  
  6484.   currentIconsThumbnail = targetBox;
  6485.  
  6486.   checkThumbnailIconsState();
  6487.   showThumbnailIcons();
  6488. }
  6489.  
  6490. function getThumbnailBackButton() {
  6491.   if (thumbnailBackButtonObject == null) {
  6492.     if (newThumbnailStyle) {
  6493.       thumbnailBackButtonObject = document.getElementById("thumb-newback");
  6494.     } else {
  6495.       thumbnailBackButtonObject = document.getElementById("thumb-back");
  6496.     }
  6497.   }
  6498.   return thumbnailBackButtonObject;
  6499. }
  6500.  
  6501. function getThumbnailForwardButton() {
  6502.   if (thumbnailForwardButtonObject == null) {
  6503.     if (newThumbnailStyle) {
  6504.       thumbnailForwardButtonObject = document.getElementById("thumb-newforward");
  6505.     } else {
  6506.       thumbnailForwardButtonObject = document.getElementById("thumb-forward");
  6507.     }
  6508.   }
  6509.   return thumbnailForwardButtonObject;
  6510. }
  6511.  
  6512. function getThumbnailReloadButton() {
  6513.   if (thumbnailReloadButtonObject == null) {
  6514.     thumbnailReloadButtonObject = document.getElementById("thumb-reload");
  6515.   }
  6516.   return thumbnailReloadButtonObject;
  6517. }
  6518.  
  6519. function getThumbnailHistoryButton() {
  6520.   if (thumbnailHistoryButtonObject == null) {
  6521.     thumbnailHistoryButtonObject = document.getElementById("thumb-history");
  6522.   }
  6523.   return thumbnailHistoryButtonObject;
  6524. }
  6525.  
  6526. function getThumbnailStopButton() {
  6527.   if (thumbnailStopButtonObject == null) {
  6528.     thumbnailStopButtonObject = document.getElementById("thumb-stop");
  6529.   }
  6530.   return thumbnailStopButtonObject;
  6531. }
  6532.  
  6533. function checkThumbnailIconsState() {
  6534.   if (thumbnailBackButton) {
  6535.     var backButton = getThumbnailBackButton();
  6536.     if (currentIconsThumbnail.showcaseTab.targetTab.canGoBack) {
  6537.       backButton.removeAttribute("disabled");
  6538.     } else {
  6539.       backButton.setAttribute("disabled", true);
  6540.     }
  6541.   }
  6542.   if (thumbnailForwardButton) {
  6543.     var forwardButton = getThumbnailForwardButton();
  6544.     if (currentIconsThumbnail.showcaseTab.targetTab.canGoForward) {
  6545.       forwardButton.removeAttribute("disabled");
  6546.     } else {
  6547.       forwardButton.setAttribute("disabled", true);
  6548.     }
  6549.   }
  6550.   if (thumbnailReloadButton) {
  6551.     var reloadButton = getThumbnailReloadButton();
  6552.  
  6553.     var location;
  6554.     if (currentIconsThumbnail.showcaseTab.targetTab.currentURI) {
  6555.       location = currentIconsThumbnail.showcaseTab.targetTab.currentURI.spec;
  6556.     } else {
  6557.       location = "about:blank";
  6558.     }
  6559.  
  6560.     if (location == "about:blank" || location == "") {
  6561.       reloadButton.setAttribute("disabled", true);
  6562.     } else {
  6563.       reloadButton.removeAttribute("disabled");
  6564.     }
  6565.   }
  6566.   if (thumbnailStopButton) {
  6567.     var stopButton = getThumbnailStopButton();
  6568.  
  6569.     if (currentIconsThumbnail.showcaseTab.showcaseProgressListener.progressListener.isLoading) {
  6570.       stopButton.removeAttribute("disabled");
  6571.     } else {
  6572.       stopButton.setAttribute("disabled", true);
  6573.     }
  6574.   }
  6575.   if (thumbnailHistoryButton) {
  6576.     var historyButton = getThumbnailHistoryButton();
  6577.     if (currentIconsThumbnail.showcaseTab.targetTab.canGoForward || currentIconsThumbnail.showcaseTab.targetTab.canGoBack) {
  6578.       historyButton.removeAttribute("disabled");
  6579.     } else {
  6580.       historyButton.setAttribute("disabled", true);
  6581.     }
  6582.   }
  6583. }
  6584.  
  6585. function showThumbnailIcons() {
  6586.   if (inZoomMode) return;
  6587.  
  6588.   var currentCanvasBox = document.getBoxObjectFor(currentIconsThumbnail.showcaseCanvas);
  6589.   
  6590.   if (newThumbnailStyle) {
  6591.     if (currentCanvasBox.width >= 5*16) {
  6592.       var currentScrollX = {};
  6593.       var currentScrollY = {};
  6594.       var topScreenX;
  6595.       var topScreenY;
  6596.       if (scrollBoxObject) {
  6597.         scrollBoxObject.getPosition(currentScrollX, currentScrollY);
  6598.         topScreenX = scrollBoxObject.screenX;
  6599.         topScreenY = scrollBoxObject.screenY;
  6600.       } else {
  6601.         currentScrollX.value = 0;
  6602.         currentScrollY.value = 0;
  6603.         topScreenX = showcaseBox.boxObject.screenX;
  6604.         topScreenY = showcaseBox.boxObject.screenY;
  6605.       }
  6606.       var canvasLeft = currentCanvasBox.screenX - topScreenX + currentScrollX.value;
  6607.       var baseline = currentCanvasBox.screenY - topScreenY + currentScrollY.value + currentCanvasBox.height -1;
  6608.       
  6609.       var centerPieces = 0;
  6610.       if (thumbnailBackButton) {
  6611.         centerPieces++;
  6612.       }
  6613.       if (thumbnailForwardButton) {
  6614.         centerPieces++;
  6615.       }
  6616.       if (thumbnailHistoryButton) {
  6617.         centerPieces++;
  6618.       }
  6619.       
  6620.       if (thumbnailBackButton) {
  6621.         var backButton = getThumbnailBackButton();
  6622.         backButton.setAttribute("collapsed", false);
  6623.         backButton.setAttribute("top", baseline - backButton.boxObject.height);
  6624.         backButton.setAttribute("left", canvasLeft + Math.floor(currentCanvasBox.width / 2 - backButton.boxObject.width * centerPieces / 2));
  6625.       }
  6626.       if (thumbnailForwardButton) {
  6627.         var forwardButton = getThumbnailForwardButton();
  6628.         forwardButton.setAttribute("collapsed", false);
  6629.         forwardButton.setAttribute("top", baseline - forwardButton.boxObject.height);
  6630.         forwardButton.setAttribute("left", canvasLeft + Math.floor(currentCanvasBox.width / 2 + forwardButton.boxObject.width * (centerPieces - 2) / 2));
  6631.       }
  6632.       if (thumbnailHistoryButton) {
  6633.         var historyButton = getThumbnailHistoryButton();
  6634.         historyButton.setAttribute("collapsed", false);
  6635.         historyButton.setAttribute("top", baseline - historyButton.boxObject.height);
  6636.         if (centerPieces == 1) {
  6637.           historyButton.setAttribute("left", canvasLeft + Math.floor(currentCanvasBox.width / 2 - historyButton.boxObject.width / 2));
  6638.         } else {
  6639.           historyButton.setAttribute("left", canvasLeft + Math.floor(currentCanvasBox.width / 2 - historyButton.boxObject.width * (centerPieces - 2) / 2));
  6640.         }
  6641.       }
  6642.       if (thumbnailStopButton) {
  6643.         var stopButton = getThumbnailStopButton();
  6644.         stopButton.setAttribute("collapsed", false);
  6645.         stopButton.setAttribute("top", baseline - stopButton.boxObject.height);
  6646.         stopButton.setAttribute("left", canvasLeft);
  6647.       }
  6648.       if (thumbnailReloadButton) {
  6649.         var reloadButton = getThumbnailReloadButton();
  6650.         reloadButton.setAttribute("collapsed", false);
  6651.         reloadButton.setAttribute("top", baseline - reloadButton.boxObject.height);
  6652.         reloadButton.setAttribute("left", canvasLeft + currentCanvasBox.width - reloadButton.boxObject.width);
  6653.       }
  6654.     }
  6655.   } else {
  6656.     // Count icons
  6657.     var numIcons = 0;
  6658.     var buttonsWidth = 0;
  6659.     var reachedWidthLimit = false;
  6660.   
  6661.     if (thumbnailBackButton && !reachedWidthLimit) {
  6662.       var backButton = getThumbnailBackButton();
  6663.       backButton.setAttribute("collapsed", false);
  6664.       if ((buttonsWidth + backButton.boxObject.width) <= currentCanvasBox.width) {
  6665.         buttonsWidth += backButton.boxObject.width;
  6666.         numIcons++;
  6667.       } else {
  6668.         reachedWidthLimit = true;
  6669.         backButton.setAttribute("collapsed", true);
  6670.       }
  6671.     }
  6672.     if (thumbnailForwardButton && !reachedWidthLimit) {
  6673.       var forwardButton = getThumbnailForwardButton();
  6674.       forwardButton.setAttribute("collapsed", false);
  6675.       if ((buttonsWidth + forwardButton.boxObject.width) <= currentCanvasBox.width) {
  6676.         buttonsWidth += forwardButton.boxObject.width;
  6677.         numIcons++;
  6678.       } else {
  6679.         reachedWidthLimit = true;
  6680.         forwardButton.setAttribute("collapsed", true);
  6681.       }
  6682.     }
  6683.     if (thumbnailStopButton && !reachedWidthLimit) {
  6684.       var stopButton = getThumbnailStopButton();
  6685.       stopButton.setAttribute("collapsed", false);
  6686.       if ((buttonsWidth + stopButton.boxObject.width) <= currentCanvasBox.width) {
  6687.         buttonsWidth += stopButton.boxObject.width;
  6688.         numIcons++;
  6689.       } else {
  6690.         reachedWidthLimit = true;
  6691.         stopButton.setAttribute("collapsed", true);
  6692.       }
  6693.     }
  6694.     if (thumbnailReloadButton && !reachedWidthLimit) {
  6695.       var reloadButton = getThumbnailReloadButton();
  6696.       reloadButton.setAttribute("collapsed", false);
  6697.       if ((buttonsWidth + reloadButton.boxObject.width) <= currentCanvasBox.width) {
  6698.         buttonsWidth += reloadButton.boxObject.width;
  6699.         numIcons++;
  6700.       } else {
  6701.         reachedWidthLimit = true;
  6702.         reloadButton.setAttribute("collapsed", true);
  6703.       }
  6704.     }
  6705.   
  6706.     if (numIcons == 0) return;
  6707.   
  6708.     // Determine thumbnail data
  6709.     var currentScrollX = {};
  6710.     var currentScrollY = {};
  6711.     var topScreenX;
  6712.     var topScreenY;
  6713.     if (scrollBoxObject) {
  6714.       scrollBoxObject.getPosition(currentScrollX, currentScrollY);
  6715.       topScreenX = scrollBoxObject.screenX;
  6716.       topScreenY = scrollBoxObject.screenY;
  6717.     } else {
  6718.       currentScrollX.value = 0;
  6719.       currentScrollY.value = 0;
  6720.       topScreenX = showcaseBox.boxObject.screenX;
  6721.       topScreenY = showcaseBox.boxObject.screenY;
  6722.     }
  6723.   
  6724.     var canvasLeft = currentCanvasBox.screenX - topScreenX + currentScrollX.value;
  6725.     var baseline = currentCanvasBox.screenY - topScreenY + currentScrollY.value + currentCanvasBox.height -1;
  6726.   
  6727.     var currentPosition = 1;
  6728.   
  6729.     var lastEnd = 0;
  6730.     // Locate and make visible
  6731.     if (thumbnailBackButton && (currentPosition <= numIcons)) {
  6732.       var backButton = getThumbnailBackButton();
  6733.       backButton.setAttribute("top", baseline - backButton.boxObject.height);
  6734.       var newLeft = canvasLeft + thumbIconCalculatePosition(currentPosition, numIcons, currentCanvasBox.width, backButton.boxObject.width);
  6735.       if (newLeft < lastEnd) {
  6736.         backButton.setAttribute("left", lastEnd);
  6737.         lastEnd = lastEnd + backButton.boxObject.width;
  6738.       } else {
  6739.         backButton.setAttribute("left", newLeft);
  6740.         lastEnd = newLeft + backButton.boxObject.width;
  6741.       }
  6742.       currentPosition++;
  6743.     }
  6744.     if (thumbnailForwardButton && (currentPosition <= numIcons)) {
  6745.       var forwardButton = getThumbnailForwardButton();
  6746.       forwardButton.setAttribute("top", baseline - forwardButton.boxObject.height);
  6747.       var newLeft = canvasLeft + thumbIconCalculatePosition(currentPosition, numIcons, currentCanvasBox.width, forwardButton.boxObject.width);
  6748.       if (newLeft < lastEnd) {
  6749.         forwardButton.setAttribute("left", lastEnd);
  6750.         lastEnd = lastEnd + forwardButton.boxObject.width;
  6751.       } else {
  6752.         forwardButton.setAttribute("left", newLeft);
  6753.         lastEnd = newLeft + forwardButton.boxObject.width;
  6754.       }
  6755.       currentPosition++;
  6756.     }
  6757.     if (thumbnailStopButton && (currentPosition <= numIcons)) {
  6758.       var stopButton = getThumbnailStopButton();
  6759.       stopButton.setAttribute("top", baseline - stopButton.boxObject.height);
  6760.       var newLeft = canvasLeft + thumbIconCalculatePosition(currentPosition, numIcons, currentCanvasBox.width, stopButton.boxObject.width);
  6761.       if (newLeft < lastEnd) {
  6762.         stopButton.setAttribute("left", lastEnd);
  6763.         lastEnd = lastEnd + stopButton.boxObject.width;
  6764.       } else {
  6765.         stopButton.setAttribute("left", newLeft);
  6766.         lastEnd = newLeft + stopButton.boxObject.width;
  6767.       }
  6768.       currentPosition++;
  6769.     }
  6770.     if (thumbnailReloadButton && (currentPosition <= numIcons)) {
  6771.       var reloadButton = getThumbnailReloadButton();
  6772.       reloadButton.setAttribute("top", baseline - reloadButton.boxObject.height);
  6773.       var newLeft = canvasLeft + thumbIconCalculatePosition(currentPosition, numIcons, currentCanvasBox.width, reloadButton.boxObject.width);
  6774.       if (newLeft < lastEnd) {
  6775.         reloadButton.setAttribute("left", lastEnd);
  6776.         lastEnd = lastEnd + reloadButton.boxObject.width;
  6777.       } else {
  6778.         reloadButton.setAttribute("left", newLeft);
  6779.         lastEnd = newLeft + reloadButton.boxObject.width;
  6780.       }
  6781.       currentPosition++;
  6782.     }
  6783.   }
  6784. }
  6785.  
  6786.  
  6787. function thumbIconCalculatePosition(currentPosition, totalPositions, width, iconWidth) {
  6788.   if (totalPositions == 1) {
  6789.     return (width / 2) - (iconWidth / 2);
  6790.   } else {
  6791.     if (currentPosition == 1) {
  6792.       return 1;
  6793.     } else if (currentPosition == totalPositions) {
  6794.       return width - iconWidth - 1;
  6795.     } else {
  6796.       if (totalPositions == 3) {
  6797.         return (width / 2) - (iconWidth / 2);
  6798.       } else if (currentPosition == 2) {
  6799.         return (width / 3) - (iconWidth / 2);
  6800.       } else { //if (currentPosition == 3) {
  6801.         return (2 * width / 3) - (iconWidth / 2);
  6802.       }
  6803.     }
  6804.   }
  6805. }
  6806.  
  6807. function thumbIconPopulateBackMenu(event) {
  6808.   
  6809.   var menu = event.target;
  6810.           
  6811.   while (menu.firstChild)
  6812.     menu.removeChild(menu.firstChild);
  6813.  
  6814.   if ((currentIconsThumbnail)&&(currentIconsThumbnail.showcaseTab.targetTab.sessionHistory)) {
  6815.     var sessionHistory = currentIconsThumbnail.showcaseTab.targetTab.sessionHistory;
  6816.   
  6817.     var index = sessionHistory.index;
  6818.     var entry;
  6819.   
  6820.     var end = (index > 8) ? index - 8 : 0;
  6821.     if ((index - 1) < end) return false;
  6822.     for (var pos = index - 1; pos >= end; pos--) {
  6823.       entry = sessionHistory.getEntryAtIndex(pos, false);
  6824.       if (entry) {
  6825.         var menuitem = document.createElement("menuitem");
  6826.         menuitem.setAttribute("label", entry.title);
  6827.         menuitem.setAttribute("index", pos);
  6828.         menu.appendChild(menuitem);
  6829.       }
  6830.     }
  6831.   }
  6832.   return true;
  6833. }
  6834.  
  6835. function thumbIconPopulateForwardMenu(event) {
  6836.   var menu = event.target;
  6837.           
  6838.   while (menu.firstChild)
  6839.     menu.removeChild(menu.firstChild);
  6840.  
  6841.   if ((currentIconsThumbnail)&&(currentIconsThumbnail.showcaseTab.targetTab.sessionHistory)) {
  6842.     var sessionHistory = currentIconsThumbnail.showcaseTab.targetTab.sessionHistory;
  6843.   
  6844.     var index = sessionHistory.index;
  6845.     var count = sessionHistory.count;
  6846.     var entry;
  6847.     var end  = ((count-index) > 8) ? index + 8 : count - 1;
  6848.     if ((index + 1) > end) return false;
  6849.     for (var pos = index + 1; pos <= end; pos++) {
  6850.       entry = sessionHistory.getEntryAtIndex(pos, false);
  6851.       if (entry) {
  6852.         var menuitem = document.createElement("menuitem");
  6853.         menuitem.setAttribute("label", entry.title);
  6854.         menuitem.setAttribute("index", pos);
  6855.         menu.appendChild(menuitem);
  6856.       }
  6857.     }
  6858.   }
  6859.   return true;
  6860. }
  6861.  
  6862. function thumbIconPopulateHistoryMenu(event) {
  6863.   var menu = event.target;
  6864.  
  6865.   while (menu.firstChild)
  6866.     menu.removeChild(menu.firstChild);
  6867.  
  6868.   var targetBrowser = currentIconsThumbnail.showcaseTab.targetTab;
  6869.   if ((targetBrowser) && (targetBrowser.docShell)) {
  6870.     var sessionHistory = targetBrowser.sessionHistory;
  6871.  
  6872.     if (sessionHistory.count == 1)
  6873.       return false;
  6874.  
  6875.     var fis = Components.classes["@mozilla.org/browser/favicon-service;1"]
  6876.                         .getService(Components.interfaces.nsIFaviconService);
  6877.  
  6878.     var start = Math.min(sessionHistory.count - 1, sessionHistory.index + 5);
  6879.     var end = Math.max(0, sessionHistory.index - 5);
  6880.  
  6881.     for (var pos = start; pos >= end; pos--) {
  6882.       var entry = sessionHistory.getEntryAtIndex(pos, false);
  6883.       if (entry) {
  6884.         var menuitem = document.createElement("menuitem");
  6885.         menuitem.setAttribute("label", entry.title);
  6886.         menuitem.setAttribute("tooltiptext", entry.title);
  6887.         menuitem.setAttribute("index", pos);
  6888.  
  6889.         if (pos == sessionHistory.index) {
  6890.           menuitem.setAttribute("class", "tbs-history-current");
  6891.           menuitem.setAttribute("type", "radio");
  6892.           menuitem.setAttribute("checked", "true");
  6893.         }
  6894.         else {
  6895.           if (pos > sessionHistory.index)
  6896.             menuitem.setAttribute("class", "menuitem-iconic tbs-history-forward");
  6897.           else
  6898.             menuitem.setAttribute("class", "menuitem-iconic tbs-history-back");
  6899.  
  6900.           try {
  6901.             var iconURL = fis.getFaviconForPage(entry.URI).spec;
  6902.             menuitem.style.listStyleImage = "url(" + iconURL + ")";
  6903.           } catch (ex) {}
  6904.         }
  6905.  
  6906.         menu.appendChild(menuitem);
  6907.       }
  6908.     }
  6909.   }
  6910.   return true;
  6911. }
  6912.  
  6913. function thumbIconGoToHistoryIndex(event) {
  6914.   var index = event.target.getAttribute("index");
  6915.  
  6916.   if (!index)
  6917.     return false;
  6918.  
  6919.   var targetWindow = getProcessedWindowForProcessedTab(currentIconsThumbnail.showcaseTab).targetWindow;
  6920.  
  6921.   var where;
  6922.   if (targetWindow.whereToOpenLink) {
  6923.     where = targetWindow.whereToOpenLink(event);
  6924.   } else {
  6925.     where = "current";
  6926.   }
  6927.  
  6928.   if (where == "current") {
  6929.     // Normal click.  Go there in the current tab and update session history.
  6930.     currentIconsThumbnail.showcaseTab.targetTab.gotoIndex(index);
  6931.     return true;
  6932.   } else {
  6933.     // Modified click.  Go there in a new tab/window.
  6934.     // This code doesn't copy history or work well with framed pages.
  6935.  
  6936.     var sessionHistory = currentIconsThumbnail.showcaseTab.targetTab.sessionHistory;
  6937.     var entry = sessionHistory.getEntryAtIndex(index, false);
  6938.     var url = entry.URI.spec;
  6939.     targetWindow.openUILinkIn(url, where);
  6940.     return true;
  6941.   }
  6942. }
  6943.  
  6944. function thumbIconBackCommand(event) {
  6945.   if ((!currentIconsThumbnail.showcaseTab.targetTab)||(!currentIconsThumbnail.showcaseTab.targetTab.docShell))
  6946.     return;
  6947.  
  6948.   if (event) {
  6949.     var targetWindow = getProcessedWindowForProcessedTab(currentIconsThumbnail.showcaseTab).targetWindow;
  6950.  
  6951.     var where;
  6952.     if (targetWindow.whereToOpenLink) {
  6953.       where = targetWindow.whereToOpenLink(event, false, false);
  6954.     } else {
  6955.       where = "current";
  6956.     }
  6957.  
  6958.     if (where == "current") {
  6959.       currentIconsThumbnail.showcaseTab.targetTab.goBack();
  6960.     } else {
  6961.       var sessionHistory = currentIconsThumbnail.showcaseTab.targetTab.sessionHistory;
  6962.       var currentIndex = sessionHistory.index;
  6963.       var entry = sessionHistory.getEntryAtIndex(currentIndex - 1, false);
  6964.       var url = entry.URI.spec;
  6965.       targetWindow.openUILinkIn(url, where);
  6966.     }
  6967.   } else {
  6968.     currentIconsThumbnail.showcaseTab.targetTab.goBack();
  6969.   }
  6970. }
  6971.  
  6972. function thumbIconForwardCommand(event) {
  6973.   if ((!currentIconsThumbnail.showcaseTab.targetTab)||(!currentIconsThumbnail.showcaseTab.targetTab.docShell))
  6974.     return;
  6975.  
  6976.   if (event) {
  6977.     var targetWindow = getProcessedWindowForProcessedTab(currentIconsThumbnail.showcaseTab).targetWindow;
  6978.  
  6979.     var where;
  6980.     if (targetWindow.whereToOpenLink) {
  6981.       where = targetWindow.whereToOpenLink(event, false, false);
  6982.     } else {
  6983.       where = "current";
  6984.     }
  6985.  
  6986.     if (where == "current") {
  6987.       currentIconsThumbnail.showcaseTab.targetTab.goForward();
  6988.     } else {
  6989.       var sessionHistory = currentIconsThumbnail.showcaseTab.targetTab.sessionHistory;
  6990.       var currentIndex = sessionHistory.index;
  6991.       var entry = sessionHistory.getEntryAtIndex(currentIndex + 1, false);
  6992.       var url = entry.URI.spec;
  6993.       targetWindow.openUILinkIn(url, where);
  6994.     }
  6995.   } else {
  6996.     currentIconsThumbnail.showcaseTab.targetTab.goForward();
  6997.   }
  6998. }
  6999.  
  7000. function thumbIconCheckMiddleClick(node, event) {
  7001.   if (event.button == 1) {
  7002.     var func = new Function("event",node.getAttribute("oncommand"));
  7003.     func.call(node,event);
  7004.     if ("tagName" in node) {
  7005.       if (node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" && (node.tagName == "menupopup" || node.tagName == "popup"))
  7006.         node.hidePopup();
  7007.     }
  7008.   }
  7009. }
  7010.  
  7011. function thumbIconReloadCommand(event) {
  7012.   if (event.shiftKey) {
  7013.     currentIconsThumbnail.showcaseTab.targetTab.webNavigation.reload(RELOAD_SKIP_CACHE_FLAGS);
  7014.   } else {
  7015.     currentIconsThumbnail.showcaseTab.targetTab.webNavigation.reload(RELOAD_FLAGS);
  7016.   }
  7017. }
  7018.  
  7019. function thumbIconStopCommand() {
  7020.   currentIconsThumbnail.showcaseTab.targetTab.webNavigation.stop(nsIWebNavigation.STOP_ALL);
  7021. }
  7022.  
  7023. function hideThumbnailIcons() {
  7024.   if (thumbnailBackButton) {
  7025.     getThumbnailBackButton().setAttribute("collapsed", true);
  7026.   }
  7027.   if (thumbnailForwardButton) {
  7028.     getThumbnailForwardButton().setAttribute("collapsed", true);
  7029.   }
  7030.   if (thumbnailStopButton) {
  7031.     getThumbnailStopButton().setAttribute("collapsed", true);
  7032.   }
  7033.   if (thumbnailReloadButton) {
  7034.     getThumbnailReloadButton().setAttribute("collapsed", true);
  7035.   }
  7036.   if (thumbnailHistoryButton) {
  7037.     getThumbnailHistoryButton().setAttribute("collapsed", true);
  7038.   }
  7039. }
  7040.  
  7041. // Log
  7042.  
  7043. function log(msg) {
  7044.   var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
  7045.                                  .getService(Components.interfaces.nsIConsoleService);
  7046.   consoleService.logStringMessage(msg);
  7047. }
  7048.